/**
 * Preset Manager
 * Handles VNA configuration presets
 */

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

const { SUCCESS, ERROR } = NOTIFICATION_TYPES;

export class PresetManager {
    constructor(notifications) {
        this.notifications = notifications;
        this.currentPreset = null;
        this.elements = {};
        this.debouncer = new Debouncer();
        this.reqGuard = new RequestGuard();

        this.handlePresetChange = this.handlePresetChange.bind(this);
        this.handleSetPreset = this.handleSetPreset.bind(this);
    }

    init(elements) {
        this.elements = elements;
        this.elements.presetDropdown?.addEventListener('change', this.handlePresetChange);
        this.elements.setPresetBtn?.addEventListener('click', this.handleSetPreset);
    }

    destroy() {
        this.elements.presetDropdown?.removeEventListener('change', this.handlePresetChange);
        this.elements.setPresetBtn?.removeEventListener('click', this.handleSetPreset);
    }

    async loadPresets() {
        try {
            const presets = await apiGet(API.SETTINGS.PRESETS);
            this.populateDropdown(presets);
        } catch (e) {
            console.error('Presets load failed:', e);
            this.notify(ERROR, 'Ошибка загрузки', 'Не удалось загрузить пресеты конфигурации');
        }
    }

    populateDropdown(presets) {
        const dd = this.elements.presetDropdown;
        dd.innerHTML = '';

        if (!presets.length) {
            dd.innerHTML = '<option value="">Пресеты отсутствуют</option>';
            dd.disabled = true;
            if (this.elements.setPresetBtn) {
                this.elements.setPresetBtn.disabled = true;
            }
            return;
        }

        dd.innerHTML = '<option value="">Выберите пресет...</option>';
        presets.forEach(p => {
            const opt = document.createElement('option');
            opt.value = p.filename;
            opt.textContent = this.formatDisplay(p);
            dd.appendChild(opt);
        });

        dd.disabled = false;
        this.syncSelectedPreset();
    }

    formatDisplay(p) {
        if (!p) return '';

        const parts = [];
        if (p.mode) {
            parts.push(p.mode.toUpperCase());
        }

        const start = this.formatFrequency(p.start_freq);
        const stop = this.formatFrequency(p.stop_freq);
        if (start && stop) {
            parts.push(`${start} – ${stop}`);
        } else if (start || stop) {
            parts.push(start || stop);
        }

        if (p.points) {
            parts.push(`${p.points} точек`);
        }

        const bandwidth = this.formatFrequency(p.bandwidth);
        if (bandwidth) {
            parts.push(`ПП ${bandwidth}`);
        }

        if (!parts.length && p.filename) {
            return p.filename;
        }

        return parts.join(' • ');
    }

    formatFrequency(value) {
        if (value === null || value === undefined) return null;
        const numeric = Number(value);
        if (!Number.isFinite(numeric) || numeric <= 0) return null;

        const units = [
            { divider: 1e9, suffix: 'ГГц' },
            { divider: 1e6, suffix: 'МГц' },
            { divider: 1e3, suffix: 'кГц' },
        ];

        for (const unit of units) {
            if (numeric >= unit.divider) {
                const scaled = numeric / unit.divider;
                const formatted = scaled >= 10 ? scaled.toFixed(0) : scaled.toFixed(2);
                return `${formatted} ${unit.suffix}`;
            }
        }

        return `${numeric.toFixed(0)} Гц`;
    }

    handlePresetChange() {
        this.updateSetButtonState();
    }

    async handleSetPreset() {
        const filename = this.elements.presetDropdown.value;
        if (!filename) return;

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

                    const result = await apiPost(API.SETTINGS.PRESET_SET, { filename });

                    this.notify(SUCCESS, 'Пресет применён', result.message);
                    this.currentPreset = { filename };

                    if (this.onPresetChanged) {
                        await this.onPresetChanged();
                    }
                    this.syncSelectedPreset();
                } catch (e) {
                    console.error('Set preset failed:', e);
                    this.notify(ERROR, 'Ошибка пресета', 'Не удалось применить пресет');
                } finally {
                    ButtonState.set(this.elements.setPresetBtn, { state: 'normal', icon: 'check', text: 'Сделать активным' });
                    this.updateSetButtonState();
                }
            }), TIMING.DEBOUNCE_PRESET
        );
    }

    updateStatus(status) {
        if (status.current_preset) {
            this.currentPreset = status.current_preset;
            this.elements.currentPreset.textContent = this.formatDisplay(status.current_preset);
        } else {
            this.currentPreset = null;
            this.elements.currentPreset.textContent = 'Нет';
        }
        this.syncSelectedPreset();
    }

    getCurrentPreset() {
        return this.currentPreset;
    }

    setCurrentPresetDirect(preset) {
        this.currentPreset = preset;
        if (this.elements.currentPreset) {
            this.elements.currentPreset.textContent = preset ? this.formatDisplay(preset) : 'Нет';
        }
        this.syncSelectedPreset();
    }

    syncSelectedPreset() {
        const dd = this.elements.presetDropdown;
        if (!dd) return;

        const active = this.currentPreset?.filename || '';
        if (active) {
            const hasOption = Array.from(dd.options).some(opt => opt.value === active);
            dd.value = hasOption ? active : '';
        } else {
            dd.value = '';
        }

        this.updateSetButtonState();
    }

    updateSetButtonState() {
        const dd = this.elements.presetDropdown;
        const btn = this.elements.setPresetBtn;
        if (!dd || !btn) return;

        const selected = dd.value;
        const hasSelection = selected !== '';
        const isActive = this.currentPreset?.filename === selected;
        btn.disabled = !hasSelection || isActive;
    }

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