/**
 * Reference Manager
 * Handles VNA measurement references
 */

import { Debouncer, RequestGuard, ButtonState } from '../utils.js';
import { apiGet, apiPost, apiDelete, buildUrl } from '../api-client.js';
import { API, TIMING, NOTIFICATION_TYPES } from '../constants.js';

const { SUCCESS, ERROR, WARNING } = NOTIFICATION_TYPES;

export class ReferenceManager {
    constructor(notifications) {
        this.notifications = notifications;
        this.availableReferences = [];
        this.currentReference = null;
        this.currentPreset = null;
        this.lastPresetFilename = null;
        this.elements = {};
        this.debouncer = new Debouncer();
        this.reqGuard = new RequestGuard();
        this.onReferenceUpdated = null;

        this.handleCreateReference = this.handleCreateReference.bind(this);
        this.handleReferenceChange = this.handleReferenceChange.bind(this);
        this.handleSetReference = this.handleSetReference.bind(this);
        this.handleClearReference = this.handleClearReference.bind(this);
        this.handleDeleteReference = this.handleDeleteReference.bind(this);
        this.handlePreviewReference = this.handlePreviewReference.bind(this);
    }

    init(elements) {
        this.elements = elements;
        this.elements.createReferenceBtn?.addEventListener('click', this.handleCreateReference);
        this.elements.referenceDropdown?.addEventListener('change', this.handleReferenceChange);
        this.elements.setReferenceBtn?.addEventListener('click', this.handleSetReference);
        this.elements.clearReferenceBtn?.addEventListener('click', this.handleClearReference);
        this.elements.deleteReferenceBtn?.addEventListener('click', this.handleDeleteReference);
        this.elements.previewReferenceBtn?.addEventListener('click', this.handlePreviewReference);
    }

    destroy() {
        this.elements.createReferenceBtn?.removeEventListener('click', this.handleCreateReference);
        this.elements.referenceDropdown?.removeEventListener('change', this.handleReferenceChange);
        this.elements.setReferenceBtn?.removeEventListener('click', this.handleSetReference);
        this.elements.clearReferenceBtn?.removeEventListener('click', this.handleClearReference);
        this.elements.deleteReferenceBtn?.removeEventListener('click', this.handleDeleteReference);
        this.elements.previewReferenceBtn?.removeEventListener('click', this.handlePreviewReference);
    }

    updateReferenceCount(count) {
        if (this.elements.referenceCount) {
            this.elements.referenceCount.textContent = typeof count === 'number' ? count : '-';
        }
    }

    async setCurrentPreset(preset) {
        const previousPreset = this.currentPreset?.filename ?? null;
        const newPreset = preset?.filename ?? null;

        this.currentPreset = preset;
        this.lastPresetFilename = newPreset;

        if (!preset) {
            await this.clearReferenceCache();
            this.reset();
            return;
        }

        // Clear current reference only if preset actually changed (not on initial load)
        if (previousPreset !== null && previousPreset !== newPreset) {
            await this.clearServerCurrentReference();
        }

        await this.loadReferences();
    }

    async loadReferences() {
        try {
            if (!this.currentPreset) {
                this.renderDropdown([]);
                this.updateInfo(null);
                this.updateReferenceCount(null);
                return;
            }

            const referencesUrl = buildUrl(API.SETTINGS.REFERENCES, {
                preset_filename: this.currentPreset.filename
            });
            this.availableReferences = await apiGet(referencesUrl);
            this.updateReferenceCount(this.availableReferences.length);

            const currentUrl = buildUrl(API.SETTINGS.REFERENCE_CURRENT, {
                preset_filename: this.currentPreset.filename
            });
            this.currentReference = await apiGet(currentUrl);

            this.renderDropdown(this.availableReferences);
            this.updateInfo(this.currentReference);
        } catch (error) {
            console.error('Failed to load references:', error);
            this.renderDropdown([]);
            this.updateInfo(null);
            this.updateReferenceCount(null);
        }
    }

    getCurrentReference() {
        return this.currentReference;
    }

    renderDropdown(references) {
        if (!this.elements.referenceDropdown) return;

        this.elements.referenceDropdown.innerHTML = '';

        const setBtn = this.elements.setReferenceBtn;
        const deleteBtn = this.elements.deleteReferenceBtn;
        const clearBtn = this.elements.clearReferenceBtn;
        const previewBtn = this.elements.previewReferenceBtn;

        if (references.length === 0) {
            this.elements.referenceDropdown.innerHTML = '<option value="">Эталоны отсутствуют</option>';
            this.elements.referenceDropdown.disabled = true;
            if (setBtn) setBtn.disabled = true;
            if (clearBtn) clearBtn.disabled = true;
            if (deleteBtn) deleteBtn.disabled = true;
            if (previewBtn) previewBtn.disabled = true;
        } else {
            this.elements.referenceDropdown.innerHTML = '<option value="">Выберите эталон...</option>';

            references.forEach(ref => {
                const option = document.createElement('option');
                option.value = ref.name;
                option.textContent = `${ref.name} (${new Date(ref.timestamp).toLocaleDateString()})`;
                this.elements.referenceDropdown.appendChild(option);
            });

            this.elements.referenceDropdown.disabled = false;

            if (this.currentReference) {
                this.elements.referenceDropdown.value = this.currentReference.name;
            }

            if (setBtn) setBtn.disabled = false;
            if (deleteBtn) deleteBtn.disabled = false;
            if (previewBtn) previewBtn.disabled = false;
        }

        this.updateButtons();
    }

    updateButtons() {
        const dropdown = this.elements.referenceDropdown;
        if (!dropdown) return;

        const hasSelection = dropdown.value !== '';
        const hasCurrent = this.currentReference !== null;

        const setBtn = this.elements.setReferenceBtn;
        const deleteBtn = this.elements.deleteReferenceBtn;
        const clearBtn = this.elements.clearReferenceBtn;
        const previewBtn = this.elements.previewReferenceBtn;

        if (setBtn) setBtn.disabled = !hasSelection;
        if (deleteBtn) deleteBtn.disabled = !hasSelection;
        if (clearBtn) clearBtn.disabled = !hasCurrent;
        if (previewBtn) previewBtn.disabled = !(hasSelection || hasCurrent);
    }

    updateInfo(reference) {
        this.currentReference = reference;

        if (!this.elements.currentReferenceInfo) {
            this.onReferenceUpdated?.(reference || null);
            return;
        }

        if (!reference) {
            this.elements.currentReferenceInfo.style.display = 'none';
            if (this.elements.currentReferenceName) this.elements.currentReferenceName.textContent = '—';
            if (this.elements.currentReferenceTimestamp) this.elements.currentReferenceTimestamp.textContent = '—';
            if (this.elements.currentReferenceDescription) this.elements.currentReferenceDescription.textContent = '—';
            this.onReferenceUpdated?.(null);
            this.updateButtons();
            return;
        }

        this.elements.currentReferenceInfo.style.display = 'flex';

        if (this.elements.currentReferenceName) {
            this.elements.currentReferenceName.textContent = reference.name;
        }

        if (this.elements.currentReferenceTimestamp) {
            const timestamp = new Date(reference.timestamp);
            this.elements.currentReferenceTimestamp.textContent = Number.isNaN(timestamp.getTime())
                ? '-'
                : timestamp.toLocaleString();
        }

        if (this.elements.currentReferenceDescription) {
            this.elements.currentReferenceDescription.textContent = reference.description || '—';
        }

        // Show calibration info if available
        if (this.elements.currentReferenceCalibration) {
            const calibrationInfo = reference.metadata?.calibration;
            if (calibrationInfo && calibrationInfo.calibration_name) {
                this.elements.currentReferenceCalibration.textContent = calibrationInfo.calibration_name;
                this.elements.currentReferenceCalibration.parentElement.style.display = 'flex';
            } else {
                this.elements.currentReferenceCalibration.textContent = '—';
                this.elements.currentReferenceCalibration.parentElement.style.display = 'none';
            }
        }

        this.onReferenceUpdated?.(reference);
        this.updateButtons();
    }

    async handleCreateReference() {
        const name = this.elements.referenceNameInput.value.trim();
        if (!name) {
        this.notify(WARNING, 'Нет имени', 'Введите имя эталона');
            return;
        }

        const description = this.elements.referenceDescriptionInput.value.trim();

        this.debouncer.debounce('create-reference', () =>
            this.reqGuard.runExclusive('create-reference', async () => {
                try {
                    ButtonState.set(this.elements.createReferenceBtn, { state: 'loading', icon: 'loader', text: 'Создание...' });

                    const result = await apiPost(API.SETTINGS.REFERENCE_CREATE, { name, description });

                    this.notify(SUCCESS, 'Эталон создан', result.message);

                    this.elements.referenceNameInput.value = '';
                    this.elements.referenceDescriptionInput.value = '';

                    await this.loadReferences();
                } catch (error) {
                    console.error('Create reference failed:', error);
                    this.notify(ERROR, 'Ошибка эталона', 'Не удалось создать эталон');
                } finally {
                    ButtonState.set(this.elements.createReferenceBtn, { state: 'normal', icon: 'target', text: 'Снять эталон' });
                }
            }), TIMING.DEBOUNCE_REFERENCE
        );
    }

    async handleReferenceChange() {
        this.updateButtons();

        // Show info for selected reference immediately
        const selectedName = this.elements.referenceDropdown?.value;
        if (selectedName) {
            const selectedRef = this.availableReferences.find(r => r.name === selectedName);
            if (selectedRef) {
                this.updateInfo(selectedRef);
            }
        } else {
            // If no selection, show current reference info
            this.updateInfo(this.currentReference);
        }
    }

    async handlePreviewReference() {
        const dropdown = this.elements.referenceDropdown;
        const selectedName = dropdown?.value ?? '';
        const targetName = selectedName || this.currentReference?.name;
        if (!targetName) {
            this.notify(WARNING, 'Нет данных', 'Не выбран ни один эталон для просмотра');
            return;
        }

        this.debouncer.debounce('preview-reference', () =>
            this.reqGuard.runExclusive('preview-reference', async () => {
                try {
                    ButtonState.set(this.elements.previewReferenceBtn, { state: 'loading', icon: 'loader', text: 'Загрузка...' });

                    const url = buildUrl(API.SETTINGS.REFERENCE_PLOT(targetName), {
                        preset_filename: this.currentPreset?.filename
                    });
                    const plotData = await apiGet(url);

                    if (this.onShowPlots) {
                        this.onShowPlots(plotData);
                    }
                } catch (error) {
                    console.error('Preview reference failed:', error);
                    this.notify(ERROR, 'Ошибка эталона', 'Не удалось загрузить данные эталона');
                } finally {
                    ButtonState.set(this.elements.previewReferenceBtn, { state: 'normal', icon: 'eye', text: 'Просмотр' });
                }
            })
        );
    }

    async handleSetReference() {
        const referenceName = this.elements.referenceDropdown.value;
        if (!referenceName) return;

        this.debouncer.debounce('set-reference', () =>
            this.reqGuard.runExclusive('set-reference', async () => {
                try {
                    ButtonState.set(this.elements.setReferenceBtn, { state: 'loading', icon: 'loader', text: 'Применение...' });

                    const result = await apiPost(API.SETTINGS.REFERENCE_SET, { name: referenceName });

                    this.notify(SUCCESS, 'Эталон применён', result.message);

                    await this.loadReferences();
                } catch (error) {
                    console.error('Set reference failed:', error);
                    this.notify(ERROR, 'Ошибка эталона', 'Не удалось применить эталон');
                } finally {
                    ButtonState.set(this.elements.setReferenceBtn, { state: 'normal', icon: 'check', text: 'Сделать активным' });
                }
            }), TIMING.DEBOUNCE_REFERENCE
        );
    }

    async handleClearReference() {
        this.debouncer.debounce('clear-reference', () =>
            this.reqGuard.runExclusive('clear-reference', async () => {
                try {
                    const clearBtn = this.elements.clearReferenceBtn;
                    if (clearBtn) {
                        ButtonState.set(clearBtn, { state: 'loading', icon: 'loader', text: 'Очистка...' });
                    }

                    const result = await apiDelete(API.SETTINGS.REFERENCE_CURRENT);

                    this.notify(SUCCESS, 'Эталон сброшен', result.message);

                    await this.loadReferences();
                } catch (error) {
                    console.error('Clear reference failed:', error);
                    this.notify(ERROR, 'Ошибка эталона', 'Не удалось сбросить эталон');
                } finally {
                    const clearBtn = this.elements.clearReferenceBtn;
                    if (clearBtn) {
                        ButtonState.set(clearBtn, { state: 'normal', icon: 'x', text: 'Сбросить' });
                    }
                }
            }), TIMING.DEBOUNCE_REFERENCE
        );
    }

    async handleDeleteReference() {
        const referenceName = this.elements.referenceDropdown.value;
        if (!referenceName) return;

        if (!confirm(`Удалить эталон «${referenceName}»? Это действие необратимо.`)) {
            return;
        }

        this.debouncer.debounce('delete-reference', () =>
            this.reqGuard.runExclusive('delete-reference', async () => {
                try {
                    ButtonState.set(this.elements.deleteReferenceBtn, { state: 'loading', icon: 'loader', text: 'Удаление...' });

                    const result = await apiDelete(API.SETTINGS.REFERENCE_ITEM(referenceName));

                    this.notify(SUCCESS, 'Эталон удалён', result.message);

                    await this.loadReferences();
                } catch (error) {
                    console.error('Delete reference failed:', error);
                    this.notify(ERROR, 'Ошибка эталона', 'Не удалось удалить эталон');
                } finally {
                    ButtonState.set(this.elements.deleteReferenceBtn, { state: 'normal', icon: 'trash-2', text: 'Удалить' });
                }
            }), TIMING.DEBOUNCE_REFERENCE
        );
    }

    reset() {
        this.availableReferences = [];
        this.currentReference = null;
        this.renderDropdown([]);
        this.updateInfo(null);
        this.updateReferenceCount(0);
    }

    async clearReferenceCache() {
        this.availableReferences = [];
        this.updateReferenceCount(0);
        this.updateInfo(null);
    }

    async clearServerCurrentReference() {
        try {
            await apiDelete(API.SETTINGS.REFERENCE_CURRENT);
        } catch (error) {
            if (!error?.status || error.status !== 404) {
                console.error('Failed to clear current reference', error);
            }
        }
        await this.clearReferenceCache();
    }

    notify(type, title, message) {
        this.notifications?.show?.({ type, title, message });
    }
}
