/**
 * Main app.js — Dashboard live updates, global handlers.
 *
 * Relies on pedalWS (from websocket.js) for real-time state pushes
 * and provides REST helper functions used by all pages.
 */

/* ── XSS-safe string helper ───────────────────────────────────────── */

function escapeHtml(text) {
    if (text == null) return '';
    const div = document.createElement('div');
    div.appendChild(document.createTextNode(String(text)));
    return div.innerHTML;
}

/* ── REST helpers ───────────────────────────────────────────────── */

async function apiGet(path) {
    const res = await fetch(`/api${path}`);
    if (!res.ok) throw new Error(`API GET ${path}: ${res.status}`);
    return res.json();
}

async function apiPost(path, body = {}) {
    const res = await fetch(`/api${path}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
    });
    if (!res.ok) throw new Error(`API POST ${path}: ${res.status}`);
    return res.json();
}

async function apiPut(path, body = {}) {
    const res = await fetch(`/api${path}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
    });
    if (!res.ok) throw new Error(`API PUT ${path}: ${res.status}`);
    return res.json();
}

async function apiDelete(path) {
    const res = await fetch(`/api${path}`, { method: 'DELETE' });
    if (!res.ok) throw new Error(`API DELETE ${path}: ${res.status}`);
    return res.json();
}

/* ── Dashboard updates (via WebSocket) ──────────────────────────── */

pedalWS.on('connected', (msg) => {
    if (msg.state) updateDashboardState(msg.state);
});

pedalWS.on('state', (msg) => {
    if (msg.state) updateDashboardState(msg.state);
});

pedalWS.on('preset_changed', (msg) => {
    if (msg.preset) {
        const nameEl = document.getElementById('preset-name');
        const metaEl = document.getElementById('preset-meta');
        if (nameEl) nameEl.textContent = msg.preset.name;
        if (metaEl) metaEl.textContent = `Bank ${msg.preset.bank} — Program ${msg.preset.program}`;
    }
    if (msg.state) updateDashboardState(msg.state);
});

pedalWS.on('bypass_changed', (msg) => {
    const btn = document.getElementById('bypass-btn');
    if (btn) {
        btn.textContent = msg.bypass ? 'BYPASSED' : 'ACTIVE';
        btn.classList.toggle('active', msg.bypass);
    }
});

pedalWS.on('tuner_changed', (msg) => {
    const btn = document.getElementById('tuner-btn');
    if (btn) {
        btn.textContent = msg.tuner_enabled ? 'ON' : 'OFF';
        btn.classList.toggle('active', msg.tuner_enabled);
    }
    const sBtn = document.getElementById('settings-tuner-btn');
    if (sBtn) {
        sBtn.textContent = msg.tuner_enabled ? 'ON' : 'OFF';
        sBtn.classList.toggle('active', msg.tuner_enabled);
    }
});

pedalWS.on('routing_changed', (msg) => {
    updateRoutingUI(msg.routing_mode, msg.routing_breakpoint);
});

/* ── 4CM Routing UI ────────────────────────────────────────────── */

function updateRoutingUI(mode, breakpoint) {
    // Dashboard badge
    const indicator = document.getElementById('routing-mode-indicator');
    const info = document.getElementById('routing-info');
    if (indicator) {
        indicator.setAttribute('data-mode', mode);
        if (mode === '4cm') {
            indicator.innerHTML = '<span class="badge badge-4cm">4CM</span>';
        } else {
            indicator.innerHTML = '<span class="badge badge-mono">Mono</span>';
        }
    }
    if (info) {
        info.textContent = mode === '4cm' ? `Breakpoint: ${breakpoint}` : 'Full chain';
    }

    // Settings page controls
    const toggleBtn = document.getElementById('4cm-toggle-btn');
    if (toggleBtn) {
        toggleBtn.textContent = mode === '4cm' ? 'ON' : 'OFF';
        toggleBtn.classList.toggle('active', mode === '4cm');
    }
    const bpRow = document.getElementById('breakpoint-row');
    if (bpRow) {
        bpRow.style.opacity = mode === '4cm' ? '1' : '0.4';
        bpRow.style.pointerEvents = mode === '4cm' ? 'auto' : 'none';
    }
    const bpSlider = document.getElementById('4cm-breakpoint');
    const bpText = document.getElementById('4cm-breakpoint-text');
    if (bpSlider) bpSlider.value = breakpoint;
    if (bpText) bpText.textContent = breakpoint;

    const desc = document.getElementById('4cm-routing-desc');
    if (desc) {
        if (mode === '4cm') {
            desc.innerHTML = `Input 1 (Guitar) → Pre blocks [0..${breakpoint}) → Send &nbsp;|&nbsp; Input 2 (Return) → Post blocks [${breakpoint}..] → Output`;
        } else {
            desc.textContent = 'Mono: Guitar → Full chain → Output';
        }
    }
}

async function toggle4cm() {
    const btn = document.getElementById('4cm-toggle-btn');
    const currentMode = btn && btn.classList.contains('active') ? '4cm' : 'mono';
    const newMode = currentMode === '4cm' ? 'mono' : '4cm';
    try {
        await apiPost('/routing', { routing_mode: newMode });
    } catch (e) {
        console.warn('Failed to toggle 4CM:', e);
    }
}

async function set4cmBreakpoint(val) {
    const bp = parseInt(val);
    try {
        await apiPost('/routing', { routing_breakpoint: bp });
    } catch (e) {
        console.warn('Failed to set breakpoint:', e);
    }
}

function updateDashboardState(state) {
    if (!state || !state.connected) return;

    // Preset info
    if (state.current_preset) {
        const nameEl = document.getElementById('preset-name');
        const metaEl = document.getElementById('preset-meta');
        if (nameEl) nameEl.textContent = state.current_preset.name;
        if (metaEl) metaEl.textContent = `Bank ${state.current_preset.bank} — Program ${state.current_preset.program}`;
    }

    // Bypass
    const bypassBtn = document.getElementById('bypass-btn');
    if (bypassBtn) {
        bypassBtn.textContent = state.bypass ? 'BYPASSED' : 'ACTIVE';
        bypassBtn.classList.toggle('active', state.bypass);
    }

    // Tuner
    const tunerBtn = document.getElementById('tuner-btn');
    if (tunerBtn) {
        tunerBtn.textContent = state.tuner_enabled ? 'ON' : 'OFF';
        tunerBtn.classList.toggle('active', state.tuner_enabled);
    }
    const sTunerBtn = document.getElementById('settings-tuner-btn');
    if (sTunerBtn) {
        sTunerBtn.textContent = state.tuner_enabled ? 'ON' : 'OFF';
        sTunerBtn.classList.toggle('active', state.tuner_enabled);
    }

    // Volume
    const volSlider = document.getElementById('volume-slider');
    const volText = document.getElementById('volume-text');
    const sVolSlider = document.getElementById('settings-volume');
    const sVolText = document.getElementById('settings-volume-text');
    const vol = Math.round((state.master_volume || 0.8) * 100);
    if (volSlider) volSlider.value = vol;
    if (volText) volText.textContent = vol + '%';
    if (sVolSlider) sVolSlider.value = vol;
    if (sVolText) sVolText.textContent = vol + '%';

    // NAM model
    const modelNameEl = document.getElementById('model-name');
    if (modelNameEl) modelNameEl.textContent = state.nam_model || 'None loaded';

    // IR
    const irNameEl = document.getElementById('ir-name');
    if (irNameEl) irNameEl.textContent = state.ir_name || 'None loaded';

    // 4CM Routing
    if (state.routing_mode) {
        updateRoutingUI(state.routing_mode, state.routing_breakpoint);
    }
}

/* ── Dashboard action handlers ─────────────────────────────────── */

async function toggleBypass() {
    const data = await apiPost('/bypass');
    // WS will update UI
}

async function toggleTuner() {
    const enabled = !document.getElementById('tuner-btn')?.classList.contains('active');
    const data = await apiPost('/tuner', { enabled });
}

async function setVolume(val) {
    const vol = parseInt(val) / 100;
    await apiPut('/volume', { volume: vol });
}

async function activatePreset(direction, delta) {
    const state = await apiGet('/state');
    if (!state.connected) return;
    const bank = state.current_preset?.bank || 0;
    const program = (state.current_preset?.program || 0) + delta;
    // Clamp 0-3 within the bank
    const clamped = Math.max(0, Math.min(3, program));
    if (clamped !== program) return;  // at edge
    await apiPost(`/presets/${bank}/${clamped}/activate`);
}

/* ── Initial page load: fetch state ─────────────────────────────── */

document.addEventListener('DOMContentLoaded', async () => {
    // If we're on the dashboard, fetch initial state
    if (document.getElementById('preset-name')) {
        try {
            const state = await apiGet('/state');
            updateDashboardState(state);
        } catch (e) {
            console.warn('Could not fetch initial state:', e);
        }
    }

    // Update WebSocket client count on settings page
    const wsCount = document.getElementById('ws-count');
    if (wsCount) {
        try {
            const state = await apiGet('/state');
            wsCount.textContent = pedalWS._handlers ? '1' : '0';
        } catch (e) {}
    }
});