import { apiGet, apiPut } from '../api.js';
import { canEdit, pageHeaderHTML, showToast } from '../app.js';
import { SOURCE_LANG, normalizeEntry, germanFor, escHtml as esc } from '../translations-helpers.js';
import { APP_UI_SCREENS, screenById, getVariants, variantById } from '../app-ui-screens.js';

const STORAGE_SCREEN = 'qdb_appui_screen';
const STORAGE_VARIANT = 'qdb_appui_variant';

let appStrings = [];
/** @type {Record<string, string>} key → german text */
let germanByKey = {};
let selectedScreenId = '';
/** @type {Record<string, string>} screenId → variantId */
let selectedVariantByScreen = {};
let saveTimers = {};
let savesInFlight = 0;

export async function appUiPage() {
    const app = document.getElementById('app');
    app.innerHTML = `
        ${pageHeaderHTML(
            'App UI',
            '<span id="appuiSaveStatus" class="appui-save-status" aria-live="polite"></span>',
            {
                subtitle: 'Edit German wording for the counselor app. Early version — some design details in the preview may be off.',
            },
        )}
        <div id="appuiRoot"><div class="spinner"></div></div>
    `;

    try {
        selectedScreenId = localStorage.getItem(STORAGE_SCREEN) || APP_UI_SCREENS[0].id;
        if (!screenById(selectedScreenId)) selectedScreenId = APP_UI_SCREENS[0].id;
        try {
            selectedVariantByScreen = JSON.parse(localStorage.getItem(STORAGE_VARIANT) || '{}') || {};
        } catch (_) {
            selectedVariantByScreen = {};
        }
        renderShell();
        await loadAppStrings();
    } catch (e) {
        document.getElementById('appuiRoot').innerHTML =
            `<p class="error-text" style="padding:16px">${esc(e.message)}</p>`;
    }
}

function currentVariantId(screen) {
    const variants = getVariants(screen);
    const stored = selectedVariantByScreen[screen.id];
    if (stored && variants.some(v => v.id === stored)) return stored;
    return variants[0].id;
}

function setVariant(screenId, variantId) {
    selectedVariantByScreen[screenId] = variantId;
    localStorage.setItem(STORAGE_VARIANT, JSON.stringify(selectedVariantByScreen));
}

function renderShell() {
    document.getElementById('appuiRoot').innerHTML = `
        <div class="appui-layout">
            <aside class="appui-sidebar">
                <h2 class="appui-panel-title">Screens</h2>
                <nav class="appui-screen-nav" id="appuiScreenNav" aria-label="App screens"></nav>
            </aside>

            <section class="appui-stage">
                <div class="appui-preview-card">
                    <div class="appui-variant-bar" id="appuiVariantBar" hidden></div>
                    <div class="appui-tablet-wrap">
                        <div class="appui-tablet" aria-label="Tablet preview">
                            <div class="appui-tablet-bezel">
                                <div class="appui-tablet-camera"></div>
                                <div class="appui-tablet-screen" id="appuiTabletScreen"></div>
                                <div class="appui-tablet-home"></div>
                            </div>
                        </div>
                    </div>
                </div>

                <aside class="appui-keys-panel">
                    <div class="appui-keys-head">
                        <h2 class="appui-panel-title">Text keys</h2>
                        <p class="appui-keys-meta" id="appuiKeysHint"></p>
                    </div>
                    <div class="appui-keys-list" id="appuiKeysList"></div>
                </aside>
            </section>
        </div>
    `;
    renderScreenNav();
}

function renderScreenNav() {
    const nav = document.getElementById('appuiScreenNav');
    nav.innerHTML = APP_UI_SCREENS.map(s => {
        const variants = getVariants(s);
        const multi = variants.length > 1 && variants[0].id !== 'default';
        return `
        <button type="button" class="appui-screen-btn${s.id === selectedScreenId ? ' active' : ''}"
            data-screen="${esc(s.id)}">
            <span class="appui-screen-btn-label">${esc(s.label)}</span>
            ${multi ? `<span class="appui-screen-btn-meta">${variants.length}</span>` : ''}
        </button>`;
    }).join('');

    nav.querySelectorAll('.appui-screen-btn').forEach(btn => {
        btn.addEventListener('click', () => {
            selectedScreenId = btn.dataset.screen;
            localStorage.setItem(STORAGE_SCREEN, selectedScreenId);
            renderScreenNav();
            renderWorkspace();
        });
    });
}

function renderVariantBar(screen) {
    const bar = document.getElementById('appuiVariantBar');
    const variants = getVariants(screen);
    const multi = variants.length > 1 && variants[0].id !== 'default';
    if (!multi) {
        bar.hidden = true;
        bar.innerHTML = '';
        return;
    }

    const activeId = currentVariantId(screen);
    bar.hidden = false;
    bar.innerHTML = `
        <div class="appui-variant-chips" role="tablist" aria-label="Screen states">
            ${variants.map(v => `
                <button type="button" role="tab"
                    class="appui-variant-chip${v.id === activeId ? ' active' : ''}"
                    data-variant="${esc(v.id)}"
                    aria-selected="${v.id === activeId}">
                    ${esc(v.label)}
                </button>`).join('')}
        </div>`;

    bar.querySelectorAll('.appui-variant-chip').forEach(btn => {
        btn.addEventListener('click', () => {
            setVariant(screen.id, btn.dataset.variant);
            renderWorkspace();
        });
    });
}

async function loadAppStrings() {
    const data = await apiGet('translations.php?all=1');
    appStrings = (data.appStrings || []).map(normalizeEntry).filter(e => e.type === 'app_string');

    germanByKey = {};
    appStrings.forEach(e => {
        const key = e.key || e.entityId;
        if (key) germanByKey[key] = germanFor(e);
    });

    renderWorkspace();
}

function textFor(key) {
    if (germanByKey[key] != null && germanByKey[key] !== '') return germanByKey[key];
    const entry = appStrings.find(e => (e.key || e.entityId) === key);
    if (entry) return germanFor(entry);
    return key;
}

function renderWorkspace() {
    const screen = screenById(selectedScreenId);
    const variant = variantById(screen, currentVariantId(screen));
    const focusSet = new Set(variant.focusKeys || screen.keys);

    renderVariantBar(screen);

    const hint = document.getElementById('appuiKeysHint');
    if (hint) {
        const nFocus = [...focusSet].filter(k => screen.keys.includes(k)).length;
        hint.textContent = variant.id !== 'default'
            ? `${variant.label} · ${nFocus} keys`
            : `${screen.keys.length} keys · German`;
    }

    const tablet = document.getElementById('appuiTabletScreen');
    tablet.innerHTML = variant.mock();
    fillFields(tablet);
    bindFields(tablet);

    renderKeysList(screen, focusSet);
}

function fillFields(root) {
    root.querySelectorAll('[data-appui-key]').forEach(el => {
        const key = el.dataset.appuiKey;
        el.value = textFor(key);
        el.title = key;
        el.disabled = !canEdit();
    });
}

function bindFields(root) {
    root.querySelectorAll('[data-appui-key]').forEach(el => {
        el.addEventListener('input', () => {
            const key = el.dataset.appuiKey;
            germanByKey[key] = el.value;
            syncKeyListInput(key, el.value);
            scheduleSave(key, el);
        });
        el.addEventListener('change', () => {
            const key = el.dataset.appuiKey;
            germanByKey[key] = el.value;
            scheduleSave(key, el, true);
        });
    });
}

function renderKeysList(screen, focusSet) {
    const list = document.getElementById('appuiKeysList');
    const editable = canEdit();
    const focused = screen.keys.filter(k => focusSet.has(k));
    const other = screen.keys.filter(k => !focusSet.has(k));

    const row = (key, inFocus) => {
        const val = esc(textFor(key));
        return `
            <div class="appui-key-row${inFocus ? ' in-variant' : ' out-variant'}" data-key="${esc(key)}">
                <code class="appui-key-code">${esc(key)}</code>
                <textarea class="appui-key-input" data-appui-key="${esc(key)}" rows="2"
                    ${editable ? '' : 'disabled'}>${val}</textarea>
            </div>`;
    };

    let html = '';
    if (focused.length && other.length) {
        html += `<div class="appui-keys-group-label">This state</div>`;
    }
    html += focused.map(k => row(k, true)).join('');
    if (other.length) {
        html += `<div class="appui-keys-group-label">Other keys on this screen</div>`;
        html += other.map(k => row(k, false)).join('');
    }
    list.innerHTML = html;

    list.querySelectorAll('[data-appui-key]').forEach(el => {
        el.addEventListener('input', () => {
            const key = el.dataset.appuiKey;
            germanByKey[key] = el.value;
            syncTabletField(key, el.value);
            scheduleSave(key, el);
        });
        el.addEventListener('change', () => {
            const key = el.dataset.appuiKey;
            germanByKey[key] = el.value;
            scheduleSave(key, el, true);
        });
        el.addEventListener('focus', () => {
            list.querySelectorAll('.appui-key-row').forEach(r => r.classList.remove('focused'));
            el.closest('.appui-key-row')?.classList.add('focused');
            highlightTabletKey(el.dataset.appuiKey);
        });
    });
}

function syncKeyListInput(key, value) {
    const inp = document.querySelector(`#appuiKeysList [data-appui-key="${CSS.escape(key)}"]`);
    if (inp && inp.value !== value) inp.value = value;
}

function syncTabletField(key, value) {
    document.querySelectorAll(`#appuiTabletScreen [data-appui-key="${CSS.escape(key)}"]`).forEach(el => {
        if (el.value !== value) el.value = value;
    });
}

function highlightTabletKey(key) {
    document.querySelectorAll('#appuiTabletScreen [data-appui-key]').forEach(el => {
        el.classList.toggle('appui-field-highlight', el.dataset.appuiKey === key);
    });
}

function setSaveStatus(state) {
    const el = document.getElementById('appuiSaveStatus');
    if (!el) return;
    if (state === 'saving') el.textContent = 'Saving…';
    else if (state === 'saved') el.textContent = 'Saved';
    else if (state === 'error') el.textContent = 'Save failed';
    else el.textContent = '';
}

function scheduleSave(key, el, immediate = false) {
    if (!canEdit()) return;
    clearTimeout(saveTimers[key]);
    const run = () => saveGerman(key, el);
    if (immediate) run();
    else {
        saveTimers[key] = setTimeout(run, 450);
        setSaveStatus('saving');
    }
}

async function saveGerman(key, el) {
    savesInFlight++;
    setSaveStatus('saving');
    try {
        await apiPut('translations.php', {
            type: 'app_string',
            id: key,
            languageCode: SOURCE_LANG,
            text: el.value,
        });
        germanByKey[key] = el.value;
        const entry = appStrings.find(e => (e.key || e.entityId) === key);
        if (entry) {
            entry.germanText = el.value;
            entry.translations = { ...(entry.translations || {}), [SOURCE_LANG]: el.value };
        }
        el.classList.add('save-flash');
        setTimeout(() => el.classList.remove('save-flash'), 400);
    } catch (e) {
        setSaveStatus('error');
        showToast(e.message, 'error');
    } finally {
        savesInFlight = Math.max(0, savesInFlight - 1);
        if (savesInFlight === 0) setSaveStatus('saved');
    }
}
