/**
 * context-log.js — Standalone decision-spine context and decision browser.
 */

import { S } from '../state.js';
import { api, bustCache } from '../api.js';

const $ = id => document.getElementById(id);
const esc = s => s == null ? '' : String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');

function fmtTs(ts) {
    if (!ts) return '—';
    try { return new Date(ts).toLocaleString(); } catch { return '—'; }
}

function runIdOf(run) {
    return run?.runId || run?.id || '';
}

function spineUrl(runId) {
    return '/api/runs/' + encodeURIComponent(runId) + '/decision-spine';
}

function chips(items, limit = 12) {
    const values = (items || []).filter(Boolean).slice(0, limit);
    if (!values.length) return '<span class="context-log-empty">—</span>';
    return values.map(value => `<span class="chip chip-muted">${esc(String(value).replace(/^.*\//, ''))}</span>`).join('');
}

function summaryCard(spine) {
    const artifacts = spine?.artifacts || {};
    const brief = artifacts.requestBrief || {};
    const plan = artifacts.selectionPlan || {};
    const model = spine?.summary?.modelRoute || plan.modelRoute || brief.modelPolicy || {};
    const selected = spine?.summary?.selected || plan.selected || {};
    return `<div class="context-log-summary">
        <div class="context-log-kpi"><span>Intent</span><strong>${esc(brief.intent || plan.intent || spine?.summary?.intent || '—')}</strong></div>
        <div class="context-log-kpi"><span>Risk</span><strong>${esc(brief.risk || '—')}</strong></div>
        <div class="context-log-kpi"><span>Model</span><strong>${esc(model.workerTier || '—')}${model.reviewerTier ? ` / ${esc(model.reviewerTier)}` : ''}</strong></div>
        <div class="context-log-kpi"><span>Events</span><strong>${esc(spine?.summary?.contextEvents ?? artifacts.contextLog?.length ?? 0)}</strong></div>
        <div class="context-log-kpi"><span>Decisions</span><strong>${esc(spine?.summary?.decisions ?? artifacts.decisionLog?.length ?? 0)}</strong></div>
        <div class="context-log-selection">
            <div><span>Files</span>${chips(selected.files, 18)}</div>
            <div><span>Skills</span>${chips(selected.skills, 18)}</div>
            <div><span>Specialists</span>${chips(selected.specialists, 18)}</div>
        </div>
    </div>`;
}

function contextRows(entries) {
    if (!entries?.length) {
        return '<div class="empty"><div class="empty-title">No context events for this run</div></div>';
    }
    return entries.map(entry => {
        const refs = [
            ...(entry.contextRefs || []),
            ...(entry.memoryRefs || []),
            ...(entry.fileRefs || []),
            ...(entry.evidenceRefs || []),
        ];
        return `<article class="context-log-row">
            <div class="context-log-row-head">
                <span>${esc(entry.phase || 'context')}</span>
                <span>${esc(entry.actor || 'system')}</span>
                <time>${esc(fmtTs(entry.createdAt))}</time>
            </div>
            <p>${esc(entry.reason || '')}</p>
            <div class="context-log-refs">${chips(refs, 24)}</div>
        </article>`;
    }).join('');
}

function decisionRows(entries) {
    if (!entries?.length) {
        return '<div class="empty"><div class="empty-title">No decisions for this run</div></div>';
    }
    return `<div class="context-log-decision-list">${entries.map(entry => `
        <article class="context-log-decision">
            <div class="context-log-row-head">
                <span>${esc(entry.verb || 'decision')}</span>
                <span>${esc(entry.surface || entry.actor || 'runtime')}</span>
                <time>${esc(fmtTs(entry.createdAt))}</time>
            </div>
            <strong>${esc(entry.decision || '')}</strong>
            <p>${esc(entry.reason || '')}</p>
            <div class="context-log-refs">${chips([entry.beforeRef, entry.afterRef].filter(Boolean), 6)}</div>
        </article>
    `).join('')}</div>`;
}

function renderRunRail(runs) {
    if (!runs.length) return `<div class="empty">
        <div class="empty-title">No runs recorded</div>
        <div class="empty-sub">Run a goal from the command bar and its context spine will appear here.</div>
    </div>`;
    return runs.map(run => {
        const id = runIdOf(run);
        const active = id === S.contextLogSelectedRunId;
        return `<button class="context-log-run ${active ? 'active' : ''}" data-context-run="${esc(id)}">
            <span>${esc(String(id).slice(-10) || 'run')}</span>
            <small>${esc(run.stage || run.state || run.status || 'queued')} · ${esc(fmtTs(run.createdAt || run.startedAt || run.updatedAt))}</small>
        </button>`;
    }).join('');
}

function emptyContextMain() {
    return `<div class="context-log-summary context-log-empty-state">
        <div class="context-log-kpi"><span>Runs</span><strong>0</strong></div>
        <div class="context-log-kpi"><span>Context</span><strong>—</strong></div>
        <div class="context-log-kpi"><span>Decision</span><strong>—</strong></div>
        <div class="context-log-selection">
            <div>
                <span>Start</span>
                <button class="btn btn-sm" id="context-log-run-goal-btn">Run a goal</button>
            </div>
            <div>
                <span>Expected here</span>
                ${chips(['request brief', 'selection plan', 'context events', 'decisions'])}
            </div>
            <div>
                <span>History</span>
                <span class="context-log-empty">Previous runs persist after the dashboard restarts.</span>
            </div>
        </div>
    </div>`;
}

export async function load() {
    const runs = await api('/api/runs?limit=30', 3000);
    S.contextLogRuns = Array.isArray(runs) ? runs : [];
    if (!S.contextLogSelectedRunId) {
        S.contextLogSelectedRunId = runIdOf(S.contextLogRuns[0]) || null;
    }
    if (S.contextLogSelectedRunId) {
        S.contextLogSpine = await api(spineUrl(S.contextLogSelectedRunId), 0);
    } else {
        S.contextLogSpine = null;
    }
    render();
}

export function render() {
    const host = $('context-log-view');
    if (!host) return;
    const spine = S.contextLogSpine;
    const artifacts = spine?.artifacts || {};
    const contextLog = artifacts.contextLog || [];
    const decisionLog = artifacts.decisionLog || [];
    host.innerHTML = `<div class="context-log-shell">
        <aside class="context-log-rail">
            <div class="context-log-rail-head">
                <span>Runs</span>
                <button class="btn btn-sm" id="context-log-refresh-btn">Refresh</button>
            </div>
            ${renderRunRail(S.contextLogRuns || [])}
        </aside>
        <section class="context-log-main">
            ${spine ? summaryCard(spine) : emptyContextMain()}
            <div class="context-log-grid">
                <div>
                    <div class="shd">Context events</div>
                    ${contextRows(contextLog)}
                </div>
                <div>
                    <div class="shd">Decisions</div>
                    ${decisionRows(decisionLog)}
                </div>
            </div>
        </section>
    </div>`;
    host.querySelectorAll('[data-context-run]').forEach(button => {
        button.addEventListener('click', async () => {
            S.contextLogSelectedRunId = button.dataset.contextRun || null;
            if (S.contextLogSelectedRunId) bustCache(spineUrl(S.contextLogSelectedRunId));
            await load();
        });
    });
    $('context-log-run-goal-btn')?.addEventListener('click', () => {
        window.location.hash = '#board';
        setTimeout(() => $('cmd-input')?.focus(), 100);
    });
    $('context-log-refresh-btn')?.addEventListener('click', async () => {
        bustCache('/api/runs?limit=30');
        if (S.contextLogSelectedRunId) bustCache(spineUrl(S.contextLogSelectedRunId));
        await load();
    });
}
