// Delay prediction layer — step-by-step: origin → destination → details → result
class PredictLayer extends BaseLayer {
    constructor(viz) {
        super(viz);
        this.state = 'origin';
        this.weatherOptions = [];
        this.carrierData = null;
        this.lastResult = null;
        this.origin = null;
        this.dest = null;
    }

    async activate() {
        super.activate();
        this.state = 'origin';
        this.lastResult = null;
        this.origin = null;
        this.dest = null;

        if (!this.weatherOptions.length) {
            try {
                const resp = await fetch('/api/predict/weather-options');
                const data = await resp.json();
                this.weatherOptions = data.options || [];
            } catch (e) {
                this.weatherOptions = ['Clear','Rain','Snow / Ice','Thunderstorm','Fog / Low Vis'];
            }
        }

        if (!this.carrierData) {
            try {
                const resp = await fetch('/data/carrier_reliability.json');
                this.carrierData = await resp.json();
            } catch (e) {
                console.error('Failed to load carrier data:', e);
                this.carrierData = {};
            }
        }

        this._renderPanel();
    }

    deactivate() {
        this.state = 'origin';
        this.lastResult = null;
        this.origin = null;
        this.dest = null;
        this.viz.selectedAirport = null;
        InfoPanel.clear();
        super.deactivate();
    }

    getLegendHTML() {
        return `
            <div class="layer-legend-title">Delay Predictor</div>
            <div class="layer-legend-hint">
                ML-powered delay prediction for your flight.
            </div>
        `;
    }

    // --- layer hooks ---

    onAirportClick(d) {
        if (this.state === 'origin') {
            this._setOrigin(d.id);
            return true;
        }
        if (this.state === 'destination') {
            if (d.id === this.origin) { this._goBackToOrigin(); return true; }
            this._setDest(d.id);
            return true;
        }
        if (this.state === 'details') {
            if (d.id === this.origin || d.id === this.dest) {
                this._goBackToDestination();
                return true;
            }
            this._setDest(d.id);
            return true;
        }
        if (this.state === 'result') {
            if (d.id === this.origin || d.id === this.dest) {
                this._goBackToDetails();
                return true;
            }
            this._setOrigin(d.id);
            return true;
        }
        return true;
    }

    onBackgroundClick() {
        if (this.state === 'origin') return false;
        this._goBackToOrigin();
        return true;
    }

    getNodeColor(d) {
        if (this.state === 'origin') return null;
        if (this.state === 'destination') return null;
        if (d.id === this.origin || d.id === this.dest) return null;
        return '#d1d5db';
    }

    getEdgeColor() {
        if (this.state === 'origin') return 'rgba(0,0,0,0)';
        if (this.state === 'destination') return null;
        return 'rgba(200,200,200,0.05)';
    }

    renderOverlay(ctx, t) {
        if (!this.origin || !this.dest) return;
        if (this.state !== 'details' && this.state !== 'result') return;

        const src = this.viz.projectedNodes.get(this.origin);
        const dst = this.viz.projectedNodes.get(this.dest);
        if (!src || !dst) return;

        let color = '#3b82f6';
        if (this.state === 'result' && this.lastResult) {
            const prob = this.lastResult.delay_probability;
            color = prob >= 0.7 ? '#ef4444' : prob >= 0.5 ? '#eab308' : '#22c55e';
        }

        ctx.beginPath();
        ctx.moveTo(src.x, src.y);
        ctx.lineTo(dst.x, dst.y);
        ctx.setLineDash([]);
        ctx.strokeStyle = color;
        ctx.lineWidth = 4 / t.k;
        ctx.globalAlpha = 0.9;
        ctx.stroke();
        ctx.globalAlpha = 1;
    }

    // --- state transitions ---

    _setOrigin(code) {
        this.origin = code;
        this.dest = null;
        this.lastResult = null;
        this.state = 'destination';
        this.viz.selectedAirport = code;
        this._renderPanel();
        this.viz.render();
    }

    _setDest(code) {
        this.dest = code;
        this.lastResult = null;
        this.state = 'details';
        this.viz.selectedAirport = null;
        this._renderPanel();
        this.viz.render();
    }

    _goBackToOrigin() {
        this.origin = null;
        this.dest = null;
        this.lastResult = null;
        this.state = 'origin';
        this.viz.selectedAirport = null;
        this._renderPanel();
        this.viz.render();
    }

    _goBackToDestination() {
        this.dest = null;
        this.lastResult = null;
        this.state = 'destination';
        this.viz.selectedAirport = this.origin;
        this._renderPanel();
        this.viz.render();
    }

    _goBackToDetails() {
        this.lastResult = null;
        this.state = 'details';
        this._renderPanel();
        this.viz.render();
    }

    // --- helpers ---

    _carrierName(code) {
        const names = {
            AA: 'American Airlines', DL: 'Delta Air Lines',
            UA: 'United Airlines',   WN: 'Southwest Airlines',
            B6: 'JetBlue Airways',   AS: 'Alaska Airlines',
            NK: 'Spirit Airlines',   F9: 'Frontier Airlines',
            G4: 'Allegiant Air',     HA: 'Hawaiian Airlines',
            OO: 'SkyWest Airlines',  MQ: 'Envoy Air',
            YX: 'Republic Airways',  '9E': 'Endeavor Air',
            OH: 'PSA Airlines',      SY: 'Sun Country Airlines',
        };
        return names[code] || code;
    }

    _airportName(code) {
        if (!this.viz.data?.nodes) return code;
        const n = this.viz.data.nodes.find(x => x.id === code);
        return n?.name || code;
    }

    // --- panel rendering ---

    _renderPanel() {
        const panel = InfoPanel.panel;
        if (!panel) return;
        switch (this.state) {
            case 'origin':      this._renderOriginPanel(panel); break;
            case 'destination': this._renderDestPanel(panel); break;
            case 'details':     this._renderDetailsPanel(panel); break;
            case 'result':      this._renderResultPanel(panel); break;
        }
    }

    _renderOriginPanel(panel) {
        panel.innerHTML = `
            <h2>Delay Predictor</h2>
            <p>Where are you flying from?</p>
            <div class="chain-search-wrap">
                <input type="text" id="predict-origin-input" class="chain-search"
                       placeholder="Airport code or name..." autocomplete="off">
                <div id="predict-origin-ac" class="chain-autocomplete"></div>
            </div>
        `;
        this._setupSearch('predict-origin-input', 'predict-origin-ac', (code) => {
            this._setOrigin(code);
        });
    }

    _renderDestPanel(panel) {
        panel.innerHTML = `
            <div class="chain-nav">
                <button class="chain-nav-btn" id="predict-back-origin">&larr; Change origin</button>
            </div>
            <h2>From ${this.origin}</h2>
            <p>${this._airportName(this.origin)}</p>
            <h3 style="margin-top:1rem">Where to?</h3>
            <div class="chain-search-wrap">
                <input type="text" id="predict-dest-input" class="chain-search"
                       placeholder="Destination..." autocomplete="off">
                <div id="predict-dest-ac" class="chain-autocomplete"></div>
            </div>
        `;
        document.getElementById('predict-back-origin')
            ?.addEventListener('click', () => this._goBackToOrigin());
        this._setupSearch('predict-dest-input', 'predict-dest-ac', (code) => {
            this._setDest(code);
        });
    }

    _renderDetailsPanel(panel) {
            const routeKey = `${this.origin}-${this.dest}`;
            const routeCarriers = this.carrierData?.[routeKey];
            let carriers;
            if (routeCarriers) {
                carriers = Object.keys(routeCarriers).filter(k => k !== 'gap').sort((a, b) => {
                    return (routeCarriers[b]?.flight_count || 0) - (routeCarriers[a]?.flight_count || 0);
                });
            } else {
                carriers = ['AA','DL','UA','WN','B6','AS','NK','F9','G4','HA','OO','MQ','YX','9E','OH','SY'];
            }

            const weatherOpts = this.weatherOptions.length
                ? this.weatherOptions
                : ['Clear','Rain','Snow / Ice','Thunderstorm','Fog / Low Vis'];

            const today = new Date().toISOString().slice(0, 10);

            panel.innerHTML = `
                <div class="chain-nav">
                    <button class="chain-nav-btn" id="predict-back-dest">&larr; Change destination</button>
                </div>
                <h2>${this.origin} &rarr; ${this.dest}</h2>
                <p class="predict-subtitle">${this._airportName(this.origin)} to ${this._airportName(this.dest)}</p>
                <div class="predict-form">
                    <label class="predict-field">
                        <span class="predict-field-label">Carrier</span>
                        <select id="predict-carrier" class="predict-input">
                            ${carriers.map(c => `<option value="${c}">${c} — ${this._carrierName(c)}</option>`).join('')}
                        </select>
                    </label>
                    <label class="predict-field">
                        <span class="predict-field-label">Date</span>
                        <input type="date" id="predict-date" class="predict-input" value="${today}">
                    </label>
                    <label class="predict-field">
                        <span class="predict-field-label">Departure Time</span>
                        <div style="display:flex;gap:0.4rem">
                            <select id="predict-dep-hour" class="predict-input" style="flex:1">
                                ${Array.from({length:24}, (_,h) => {
                                    const ampm = h < 12 ? 'AM' : 'PM';
                                    const h12 = h === 0 ? 12 : h > 12 ? h - 12 : h;
                                    const sel = h === 9 ? ' selected' : '';
                                    return `<option value="${h}"${sel}>${h12} ${ampm}</option>`;
                                }).join('')}
                            </select>
                            <select id="predict-dep-min" class="predict-input" style="flex:1">
                                <option value="0" selected>:00</option>
                                <option value="15">:15</option>
                                <option value="30">:30</option>
                                <option value="45">:45</option>
                            </select>
                        </div>
                    </label>
                    <label class="predict-field">
                        <span class="predict-field-label">Weather <span id="predict-weather-hint" style="font-weight:400;font-size:0.7rem;color:var(--text-muted)"></span></span>
                        <select id="predict-weather" class="predict-input">
                            ${weatherOpts.map(w => `<option value="${w}">${w}</option>`).join('')}
                        </select>
                    </label>
                    <button class="chain-explain-btn" id="predict-submit">Predict Delay</button>
                </div>
                <div id="predict-error" class="predict-error"></div>
            `;

            document.getElementById('predict-back-dest')
                ?.addEventListener('click', () => this._goBackToDestination());
            document.getElementById('predict-submit')
                ?.addEventListener('click', () => this._runPrediction());

            // Pre-select weather based on route + month, and update when date changes
            const dateInput = document.getElementById('predict-date');
            const updateWeather = () => this._preselectWeather(dateInput?.value);
            updateWeather();
            dateInput?.addEventListener('change', updateWeather);
        }
    async _preselectWeather(dateStr) {
        if (!dateStr || !this.origin || !this.dest) return;
        const month = new Date(dateStr).getMonth() + 1;
        const hint = document.getElementById('predict-weather-hint');
        const select = document.getElementById('predict-weather');
        try {
            const resp = await fetch(`/api/predict/route-weather?origin=${this.origin}&dest=${this.dest}&month=${month}`);
            const data = await resp.json();
            if (data.suggested_weather && select) {
                select.value = data.suggested_weather;
            }
            if (hint && data.rate != null) {
                const pct = (data.rate * 100).toFixed(0);
                hint.textContent = `(${pct}% historical weather delays)`;
            } else if (hint) {
                hint.textContent = '';
            }
        } catch (e) {
            // silently fall back to default
        }
    }


    async _runPrediction() {
        const carrier = document.getElementById('predict-carrier')?.value;
        const date = document.getElementById('predict-date')?.value;
        const hh = parseInt(document.getElementById('predict-dep-hour')?.value, 10);
        const mm = parseInt(document.getElementById('predict-dep-min')?.value, 10);
        const weather = document.getElementById('predict-weather')?.value;
        const errEl = document.getElementById('predict-error');

        if (!carrier || !date || isNaN(hh)) {
            if (errEl) { errEl.textContent = 'Please fill in all fields.'; errEl.style.display = 'block'; }
            return;
        }

        const depTime = hh * 100 + (mm || 0);

        const btn = document.getElementById('predict-submit');
        if (btn) { btn.disabled = true; btn.textContent = 'Predicting...'; }

        try {
            const resp = await fetch('/api/predict/', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    carrier,
                    origin: this.origin,
                    dest: this.dest,
                    crs_dep_time: depTime,
                    fl_date: date,
                    weather: weather || 'Clear',
                }),
            });
            if (!resp.ok) {
                const detail = await resp.json().catch(() => ({}));
                throw new Error(detail.detail || `Request failed (${resp.status})`);
            }
            this.lastResult = await resp.json();
            this.state = 'result';
            this._renderPanel();
            this.viz.render();
        } catch (e) {
            if (errEl) { errEl.textContent = e.message; errEl.style.display = 'block'; }
            if (btn) { btn.disabled = false; btn.textContent = 'Predict Delay'; }
        }
    }

    _renderResultPanel(panel) {
        const r = this.lastResult;
        if (!r) return;

        const prob = r.delay_probability;
        const pct = (prob * 100).toFixed(1);
        const riskLevel = prob >= 0.7 ? 'high' : prob >= 0.5 ? 'moderate' : 'low';
        const riskColors = { low: '#22c55e', moderate: '#eab308', high: '#ef4444' };
        const riskIcons = { low: '\u2713', moderate: '\u26A0', high: '\u2717' };
        const riskLabels = { low: 'Low Risk', moderate: 'Moderate Risk', high: 'High Risk' };
        const color = riskColors[riskLevel];

        panel.innerHTML = `
            <div class="chain-nav">
                <button class="chain-nav-btn" id="predict-back-details">&larr; Change details</button>
            </div>
            <h2>${this.origin} &rarr; ${this.dest}</h2>
            <p class="predict-subtitle">${this._airportName(this.origin)} to ${this._airportName(this.dest)}</p>

            <div class="predict-result-hero" style="border-color:${color}">
                <div class="predict-result-icon" style="color:${color}">${riskIcons[riskLevel]}</div>
                <div class="predict-result-pct" style="color:${color}">${pct}%</div>
                <div class="predict-result-label">${r.prediction}</div>
                <span class="chain-badge" style="background:${riskLevel === 'low' ? '#d1fae5' : riskLevel === 'moderate' ? '#fef9c3' : '#fee2e2'};color:${riskLevel === 'low' ? '#065f46' : riskLevel === 'moderate' ? '#854d0e' : '#991b1b'}">${riskLabels[riskLevel]}</span>
            </div>

            <div class="chain-verdict-section">
                <h3>Flight Details</h3>
                <div class="chain-verdict-row">
                    <span class="chain-verdict-label">Confidence</span>
                    <span class="chain-verdict-pct">${r.confidence}</span>
                </div>
                <div class="chain-verdict-row">
                    <span class="chain-verdict-label">Distance</span>
                    <span class="chain-verdict-pct">${Math.round(r.distance_miles).toLocaleString()} mi</span>
                </div>
                <div class="chain-verdict-row">
                    <span class="chain-verdict-label">Holiday week</span>
                    <span class="chain-verdict-pct">${r.is_holiday_week ? 'Yes' : 'No'} (${r.days_to_holiday}d away)</span>
                </div>
                <div class="chain-verdict-row">
                    <span class="chain-verdict-label">Peak season</span>
                    <span class="chain-verdict-pct">${r.is_peak_season ? 'Yes' : 'No'}</span>
                </div>
                <div class="chain-verdict-row">
                    <span class="chain-verdict-label">Weather</span>
                    <span class="chain-verdict-pct">${r.weather_flag ? 'Adverse' : 'Clear'}</span>
                </div>
                <div class="chain-verdict-row">
                    <span class="chain-verdict-label">Model</span>
                    <span class="chain-verdict-pct">${r.model_used}</span>
                </div>
            </div>

            <div class="chain-recommendation">
                ${prob >= 0.7 ? 'High delay risk — consider alternative times or carriers.'
                  : prob >= 0.5 ? 'Moderate delay risk — allow extra buffer time.'
                  : 'Low delay risk — this flight looks good.'}
            </div>

            <button class="chain-explain-btn" id="predict-new">New Prediction</button>
        `;

        document.getElementById('predict-back-details')
            ?.addEventListener('click', () => this._goBackToDetails());
        document.getElementById('predict-new')
            ?.addEventListener('click', () => this._goBackToOrigin());
    }

    _setupSearch(inputId, dropdownId, onSelect) {
        const input = document.getElementById(inputId);
        const dropdown = document.getElementById(dropdownId);
        if (!input || !dropdown) return;

        let activeIdx = -1;

        const getMatches = () => {
            const q = input.value.trim().toUpperCase();
            if (q.length < 1) return [];
            const pool = (this.viz.data?.nodes || []).map(n => ({
                id: n.id, name: n.name || '', flights: n.total_flights || 0,
            }));
            return pool.filter(n =>
                n.id.includes(q) || (n.name && n.name.toUpperCase().includes(q))
            ).sort((a, b) => {
                if (a.id === q) return -1;
                if (b.id === q) return 1;
                return b.flights - a.flights;
            }).slice(0, 8);
        };

        const render = () => {
            const matches = getMatches();
            const q = input.value.trim();
            if (q.length < 1) { dropdown.innerHTML = ''; dropdown.style.display = 'none'; return; }
            if (matches.length === 0) {
                dropdown.innerHTML = '<div class="chain-ac-empty">No matches</div>';
                dropdown.style.display = 'block';
                return;
            }
            dropdown.innerHTML = matches.map((m, i) => `
                <div class="chain-ac-item${i === activeIdx ? ' active' : ''}" data-code="${m.id}">
                    <strong>${m.id}</strong>
                    <span class="chain-ac-name">${m.name}</span>
                </div>
            `).join('');
            dropdown.style.display = 'block';
            dropdown.querySelectorAll('.chain-ac-item').forEach(el => {
                el.addEventListener('mousedown', (e) => { e.preventDefault(); onSelect(el.dataset.code); });
            });
        };

        input.addEventListener('input', () => { activeIdx = -1; render(); });
        input.addEventListener('focus', render);
        input.addEventListener('blur', () => { setTimeout(() => { dropdown.style.display = 'none'; }, 150); });
        input.addEventListener('keydown', (e) => {
            const items = dropdown.querySelectorAll('.chain-ac-item');
            if (e.key === 'ArrowDown') { e.preventDefault(); activeIdx = Math.min(activeIdx + 1, items.length - 1); render(); }
            else if (e.key === 'ArrowUp') { e.preventDefault(); activeIdx = Math.max(activeIdx - 1, -1); render(); }
            else if (e.key === 'Enter') { e.preventDefault(); if (activeIdx >= 0 && items[activeIdx]) onSelect(items[activeIdx].dataset.code); else if (items.length === 1) onSelect(items[0].dataset.code); }
            else if (e.key === 'Escape') { dropdown.style.display = 'none'; input.blur(); }
        });

        setTimeout(() => input.focus(), 50);
    }
}
