const $ = (id) => document.getElementById(id);

function fmt(obj) {
    return typeof obj === 'string' ? obj : JSON.stringify(obj, null, 2);
}

async function api(path, opts = {}) {
    const res = await fetch(path, {
        headers: { 'Content-Type': 'application/json', ...(opts.headers || {}) },
        ...opts,
    });
    const text = await res.text();
    let data;
    try {
        data = JSON.parse(text);
    } catch {
        data = text;
    }
    if (!res.ok) {
        const detail = data?.detail || text || res.statusText;
        throw new Error(`${res.status}: ${detail}`);
    }
    return data;
}

function initTabs() {
    const tabs = document.querySelectorAll('#debugTabs button');
    tabs.forEach((btn) => {
        btn.addEventListener('click', () => {
            tabs.forEach((t) => t.classList.remove('active'));
            btn.classList.add('active');
            document.querySelectorAll('.debug-panel').forEach((p) => p.classList.remove('active'));
            $(`panel-${btn.dataset.tab}`).classList.add('active');
        });
    });
}

async function loadConfig() {
    const c = await api('/debug/config');
    $('configOut').textContent = fmt(c);
    $('llmModel').placeholder = c.sd_prompt_model || c.system_model;
    return c;
}

async function loadPersonas() {
    const list = await api('/debug/personas');
    const sel = $('sdPersona');
    sel.innerHTML = '';
    for (const p of list) {
        const opt = document.createElement('option');
        opt.value = p.persona_id;
        opt.textContent = `${p.name} (${p.persona_id})`;
        sel.appendChild(opt);
    }
}

async function runSdPrompt() {
    $('sdScene').textContent = '…';
    $('sdPrompts').textContent = '…';
    const body = {
        persona_id: $('sdPersona').value,
        chat_excerpt: $('sdChat').value,
        outfit_json: $('sdOutfit').value || '[]',
        use_prose: $('sdUseProse') ? $('sdUseProse').checked : false,
    };
    const app = $('sdAppearance').value.trim();
    if (app) body.appearance_override = app;

    const data = await api('/debug/sd-prompt', { method: 'POST', body: JSON.stringify(body) });
    $('sdScene').textContent = data.scene ? fmt(data.scene) : (data.error || '—');
    const prompts = [];
    if (data.tags_only_full) prompts.push('=== TAGS + POV (no prose) ===\n' + data.tags_only_full);
    if (data.hybrid_full) prompts.push('\n=== HYBRID (Comfy) ===\n' + data.hybrid_full);
    if (!data.tags_only_full && data.tag_full) prompts.push('=== PROMPT ===\n' + data.tag_full);
    $('sdPrompts').textContent = prompts.join('\n') || data.error || '—';
    $('sdLlmRaw').textContent = [
        `model: ${data.sd_prompt_model}`,
        `dual: ${data.anima_dual}`,
        '',
        '--- system ---',
        data.builder_system || '',
        '',
        '--- user ---',
        data.builder_user || '',
        '',
        '--- raw ---',
        data.llm_raw || data.error || '',
    ].join('\n');
    if (data.tag_full || data.hybrid_full) {
        const src = data.hybrid_full || data.tag_full;
        const parts = src.includes('__NEGATIVE_PROMPT__') 
            ? src.split('\n\n__NEGATIVE_PROMPT__\n\n') 
            : src.includes('\n\nNegative prompt:') 
                ? src.split('\n\nNegative prompt:') 
                : [src, ''];
        $('genPositive').value = parts[0] || '';
        $('genNegative').value = parts[1] || '';
    }
}

async function runLlm() {
    $('llmOut').textContent = '…';
    const data = await api('/debug/llm', {
        method: 'POST',
        body: JSON.stringify({
            model: $('llmModel').value.trim(),
            system: $('llmSystem').value,
            user: $('llmUser').value,
        }),
    });
    $('llmOut').textContent = `model: ${data.model}\n\n${data.response}`;
}

function fillModelSelect(sel, options, configured) {
    const current = sel.querySelector('option')?.value ?? '';
    sel.innerHTML = `<option value="">— env: ${configured || '—'} —</option>`;
    for (const name of options || []) {
        const opt = document.createElement('option');
        opt.value = name;
        opt.textContent = name;
        if (name === configured) opt.selected = true;
        sel.appendChild(opt);
    }
}

async function loadComfyModels() {
    $('comfyModelLists').textContent = 'Загрузка object_info…';
    const data = await api('/debug/comfy/models');
    const { models, configured } = data;
    fillModelSelect($('genUnet'), models.unets, configured.unet);
    fillModelSelect($('genClip'), models.clips, configured.clip);
    fillModelSelect($('genVae'), models.vaes, configured.vae);
    fillModelSelect($('genCkpt'), models.checkpoints, configured.checkpoint);

    const wrap = $('comfyModelLists');
    wrap.innerHTML = '';
    for (const [key, list] of Object.entries(models)) {
        const block = document.createElement('details');
        block.className = 'model-list-block';
        block.open = key === 'unets' || key === 'checkpoints';
        block.innerHTML = `<summary>${key} (${list.length})</summary>`;
        const ul = document.createElement('ul');
        for (const item of list) {
            const li = document.createElement('li');
            li.textContent = item;
            ul.appendChild(li);
        }
        block.appendChild(ul);
        wrap.appendChild(block);
    }
}

async function comfyPing() {
    $('comfyPingOut').textContent = '…';
    const data = await api('/debug/comfy/ping');
    $('comfyPingOut').textContent = fmt(data);
}

async function comfyGenerate() {
    $('comfyGenOut').textContent = 'Генерация…';
    $('comfyImgWrap').classList.add('hidden');
    const body = {
        positive: $('genPositive').value,
        negative: $('genNegative').value,
    };
    const u = $('genUnet').value;
    const c = $('genClip').value;
    const v = $('genVae').value;
    const ck = $('genCkpt').value;
    if (u) body.unet = u;
    if (c) body.clip = c;
    if (v) body.vae = v;
    if (ck) body.checkpoint = ck;

    const data = await api('/debug/comfy/generate', {
        method: 'POST',
        body: JSON.stringify(body),
    });
    $('comfyGenOut').textContent = fmt(data);
    if (data.image_path) {
        $('comfyImg').src = data.image_path + '?t=' + Date.now();
        $('comfyImgWrap').classList.remove('hidden');
    }
}

async function comfyRaw() {
    $('comfyRawOut').textContent = '…';
    const data = await api('/debug/comfy/raw', {
        method: 'POST',
        body: JSON.stringify({
            method: $('rawMethod').value,
            path: $('rawPath').value,
            params_json: $('rawParams').value || '{}',
            body_json: $('rawBody').value || '',
        }),
    });
    $('comfyRawOut').textContent = fmt(data);
}

function bind() {
    initTabs();
    $('btnReloadConfig').addEventListener('click', loadConfig);
    $('btnSdPrompt').addEventListener('click', () => runSdPrompt().catch(showErr));
    $('btnLlm').addEventListener('click', () => runLlm().catch(showErr));
    $('btnComfyPing').addEventListener('click', () => comfyPing().catch(showErr));
    $('btnComfyModels').addEventListener('click', () => loadComfyModels().catch(showErr));
    $('btnComfyGen').addEventListener('click', () => comfyGenerate().catch(showErr));
    $('btnComfyRaw').addEventListener('click', () => comfyRaw().catch(showErr));
}

function showErr(e) {
    alert(e.message || String(e));
}

bind();
loadConfig().catch(showErr);
loadPersonas().catch(showErr);
