// terminal.js — Terminal + Host Shell
// Extracted from dashboard.html (lines 6673-7088)

// ── Terminal ─────────────────────────────────────────
const termInput = document.getElementById('terminal-input');
const termOutput = document.getElementById('terminal-output');
let termHistory = [];
let termHistIdx = -1;
let termStreaming = false;

termInput.addEventListener('keydown', e => {
    if (e.key === 'Enter' && !termStreaming) {
        terminalSend();
    } else if (e.key === 'ArrowUp') {
        e.preventDefault();
        if (termHistory.length && termHistIdx < termHistory.length - 1) {
            termHistIdx++;
            termInput.value = termHistory[termHistory.length - 1 - termHistIdx];
        }
    } else if (e.key === 'ArrowDown') {
        e.preventDefault();
        if (termHistIdx > 0) {
            termHistIdx--;
            termInput.value = termHistory[termHistory.length - 1 - termHistIdx];
        } else {
            termHistIdx = -1;
            termInput.value = '';
        }
    }
});

async function loadTerminalModel() {
    try {
        const res = await apiFetch(API + '/api/status');
        const data = await res.json();
        const el = document.getElementById('terminal-model');
        el.textContent = data.provider || '';
        el.style.color = _modelColor(data.provider || '');
    } catch (_) {}
}

function termAddLine(text, cls) {
    const line = document.createElement('div');
    line.className = 'terminal-line ' + cls;
    line.textContent = text;
    termOutput.appendChild(line);
    termOutput.scrollTop = termOutput.scrollHeight;
    return line;
}

function termFormatCode(raw) {
    // Convert triple-backtick blocks to <pre><code>
    return raw.replace(/```(?:\w*)\n([\s\S]*?)```/g, '<pre><code>$1</code></pre>');
}

async function terminalSend() {
    const text = termInput.value.trim();
    if (!text) return;

    termHistory.push(text);
    termHistIdx = -1;
    termInput.value = '';

    termAddLine(text, 'user');

    termStreaming = true;
    termInput.disabled = true;

    // Create response line with blinking cursor
    const respLine = document.createElement('div');
    respLine.className = 'terminal-line assistant';
    const cursor = document.createElement('span');
    cursor.className = 'terminal-cursor';
    respLine.appendChild(cursor);
    termOutput.appendChild(respLine);
    termOutput.scrollTop = termOutput.scrollHeight;

    let accumulated = '';

    try {
        const res = await apiFetch(API + '/api/terminal/stream', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({message: text})
        });

        const reader = res.body.getReader();
        const decoder = new TextDecoder();
        let buffer = '';

        while (true) {
            const {done, value} = await reader.read();
            if (done) break;

            buffer += decoder.decode(value, {stream: true});
            const lines = buffer.split('\n');
            buffer = lines.pop(); // keep incomplete line

            for (const line of lines) {
                if (!line.startsWith('data: ')) continue;
                let evt;
                try { evt = JSON.parse(line.slice(6)); } catch(_) { continue; }

                if (evt.type === 'text') {
                    accumulated += evt.content;
                    // Update response line (keep cursor at end)
                    respLine.innerHTML = '';
                    const span = document.createElement('span');
                    span.innerHTML = termFormatCode(escapeHtml(accumulated));
                    respLine.appendChild(span);
                    respLine.appendChild(cursor);
                    termOutput.scrollTop = termOutput.scrollHeight;
                } else if (evt.type === 'tool_start') {
                    termAddLine('[Running ' + evt.tool_name + '...]', 'tool');
                } else if (evt.type === 'tool_end') {
                    termAddLine('[Done: ' + evt.tool_name + ']', 'tool');
                } else if (evt.type === 'error') {
                    termAddLine('Error: ' + (evt.error || 'Unknown'), 'error');
                } else if (evt.type === 'done') {
                    break;
                }
            }
        }
    } catch (e) {
        termAddLine('Error: connection failed', 'error');
    }

    // Remove cursor, finalize response
    if (cursor.parentNode) cursor.remove();
    if (!accumulated) respLine.remove(); // no content produced

    termStreaming = false;
    termInput.disabled = false;
    termInput.focus();
}

// ── Host Shell Terminal ──────────────────────────────────
const shellInput = document.getElementById('shell-input');
const shellOutput = document.getElementById('shell-output');
const shellKillBtn = document.getElementById('shell-kill-btn');
let shellHistory = [];
let shellHistIdx = -1;
let shellRunning = false;

// Check if shell is enabled and show nav item
(async function checkShellEnabled() {
    try {
        const res = await apiFetch(API + '/api/shell/enabled');
        const data = await res.json();
        if (data.enabled) {
            document.getElementById('shell-nav').style.display = '';
        }
    } catch (_) {}
})();

function shellFocusInput() {
    if (shellInput) shellInput.focus();
}

function stripAnsi(str) {
    return str.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '');
}

function shellAddLine(text, cls) {
    const line = document.createElement('div');
    line.className = 'shell-line ' + cls;
    line.textContent = text;
    shellOutput.appendChild(line);
    shellOutput.scrollTop = shellOutput.scrollHeight;
    return line;
}

if (shellInput) {
    shellInput.addEventListener('keydown', e => {
        if (e.key === 'Enter' && !shellRunning) {
            shellSend();
        } else if (e.key === 'ArrowUp') {
            e.preventDefault();
            if (shellHistory.length && shellHistIdx < shellHistory.length - 1) {
                shellHistIdx++;
                shellInput.value = shellHistory[shellHistory.length - 1 - shellHistIdx];
            }
        } else if (e.key === 'ArrowDown') {
            e.preventDefault();
            if (shellHistIdx > 0) {
                shellHistIdx--;
                shellInput.value = shellHistory[shellHistory.length - 1 - shellHistIdx];
            } else {
                shellHistIdx = -1;
                shellInput.value = '';
            }
        } else if (e.key === 'c' && e.ctrlKey) {
            e.preventDefault();
            if (shellRunning) shellKill();
        }
    });
}

async function shellSend() {
    const text = shellInput.value.trim();
    if (!text) return;

    shellHistory.push(text);
    shellHistIdx = -1;
    shellInput.value = '';

    shellAddLine(text, 'command');

    shellRunning = true;
    shellInput.disabled = true;
    shellKillBtn.style.display = 'inline-block';
    document.getElementById('shell-status').textContent = 'running...';

    try {
        const res = await apiFetch(API + '/api/shell/stream', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({command: text})
        });

        if (!res.ok) {
            const err = await res.json().catch(() => ({}));
            shellAddLine(err.error || 'Request failed', 'error');
            shellRunning = false;
            shellInput.disabled = false;
            shellKillBtn.style.display = 'none';
            document.getElementById('shell-status').textContent = '';
            shellInput.focus();
            return;
        }

        const reader = res.body.getReader();
        const decoder = new TextDecoder();
        let buffer = '';

        while (true) {
            const {done, value} = await reader.read();
            if (done) break;

            buffer += decoder.decode(value, {stream: true});
            const lines = buffer.split('\n');
            buffer = lines.pop();

            for (const line of lines) {
                if (!line.startsWith('data: ')) continue;
                let evt;
                try { evt = JSON.parse(line.slice(6)); } catch(_) { continue; }

                if (evt.type === 'output') {
                    const clean = stripAnsi(evt.content).replace(/\n$/, '');
                    if (clean) shellAddLine(clean, 'output');
                } else if (evt.type === 'exit') {
                    const cls = evt.code === 0 ? 'exit-ok' : 'exit-fail';
                    shellAddLine('exit ' + evt.code, cls);
                } else if (evt.type === 'error') {
                    shellAddLine('Error: ' + (evt.error || 'Unknown'), 'error');
                } else if (evt.type === 'done') {
                    break;
                }
            }
        }
    } catch (e) {
        shellAddLine('Error: connection failed', 'error');
    }

    shellRunning = false;
    shellInput.disabled = false;
    shellKillBtn.style.display = 'none';
    document.getElementById('shell-status').textContent = '';
    shellInput.focus();
}

async function shellKill() {
    try {
        await apiFetch(API + '/api/shell/kill', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: '{}'
        });
    } catch (_) {}
}

// Model Routing
let _routingConfig = null;
const CATEGORY_ICONS = {
    simple: 'fas fa-bolt', moderate: 'fas fa-comment',
    complex: 'fas fa-brain', coding: 'fas fa-code',
    creative: 'fas fa-palette', private: 'fas fa-lock',
    long: 'fas fa-file-alt'
};

async function loadShellToggle() {
    try {
        const res = await apiFetch(API + '/api/shell/enabled');
        const data = await res.json();
        const tog = document.getElementById('toggle-shell');
        if (tog) tog.classList.toggle('on', data.enabled);
    } catch (_) {}
}

async function toggleShell() {
    const tog = document.getElementById('toggle-shell');
    const nowOn = !tog.classList.contains('on');
    try {
        const res = await apiFetch(API + '/api/shell/enabled', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({enabled: nowOn})
        });
        const data = await res.json();
        tog.classList.toggle('on', data.enabled);
        document.getElementById('shell-nav').style.display = data.enabled ? '' : 'none';
    } catch (_) {}
}

async function togglePII() {
    const tog = document.getElementById('toggle-pii');
    const nowOn = !tog.classList.contains('on');
    try {
        const res = await apiFetch(API + '/api/settings/pii', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({enabled: nowOn})
        });
        const data = await res.json();
        tog.classList.toggle('on', data.enabled);
        const st = document.getElementById('pii-status');
        st.textContent = data.enabled ? 'Active — PII will be redacted from messages' : 'Disabled';
    } catch (_) {}
}
async function loadPIIStatus() {
    try {
        const res = await apiFetch(API + '/api/settings/pii');
        const data = await res.json();
        const tog = document.getElementById('toggle-pii');
        tog.classList.toggle('on', data.enabled);
        tog.setAttribute('onclick', 'togglePII()');
        const st = document.getElementById('pii-status');
        st.textContent = data.enabled ? 'Active — PII will be redacted from messages' : '';
    } catch (_) {}
}
loadPIIStatus();

async function loadBudgetSettings() {
    try {
        const res = await apiFetch(API + '/api/settings/budget');
        const data = await res.json();
        const tog = document.getElementById('toggle-budget');
        const limitRow = document.getElementById('budget-limit-row');
        const spendRow = document.getElementById('budget-spend-row');
        const amtInput = document.getElementById('budget-amount');

        tog.classList.toggle('on', data.enabled);
        limitRow.style.display = data.enabled ? 'block' : 'none';
        if (data.daily_budget) amtInput.value = data.daily_budget.toFixed(2);

        if (data.spent_today !== undefined) {
            if (data.enabled) {
                const pct = Math.min(100, (data.spent_today / data.daily_budget) * 100).toFixed(0);
                spendRow.textContent = `Today: $${data.spent_today.toFixed(4)} / $${data.daily_budget.toFixed(2)} (${pct}% used)`;
            } else {
                spendRow.textContent = `Today: $${data.spent_today.toFixed(4)} — No limit set`;
            }
        }
    } catch (_) {}
}

async function toggleBudget() {
    const tog = document.getElementById('toggle-budget');
    const nowOn = !tog.classList.contains('on');
    const amtInput = document.getElementById('budget-amount');
    const daily = parseFloat(amtInput.value) || 10.0;
    try {
        const res = await apiFetch(API + '/api/settings/budget', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({enabled: nowOn, daily_budget: daily})
        });
        const data = await res.json();
        tog.classList.toggle('on', data.enabled);
        const limitRow = document.getElementById('budget-limit-row');
        limitRow.style.display = data.enabled ? 'block' : 'none';
        await loadBudgetSettings();
    } catch (_) {}
}

async function saveBudgetAmount() {
    const tog = document.getElementById('toggle-budget');
    const amtInput = document.getElementById('budget-amount');
    const daily = parseFloat(amtInput.value);
    if (isNaN(daily) || daily <= 0) {
        amtInput.style.borderColor = 'var(--danger, #e55)';
        return;
    }
    amtInput.style.borderColor = '';
    const enabled = tog.classList.contains('on');
    try {
        const res = await apiFetch(API + '/api/settings/budget', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({enabled, daily_budget: daily})
        });
        await res.json();
        const btn = document.getElementById('budget-save-btn');
        const orig = btn.textContent;
        btn.textContent = 'Saved ✓';
        setTimeout(() => { btn.textContent = orig; }, 1500);
        await loadBudgetSettings();
    } catch (_) {}
}

// Wire budget toggle + save button after DOM ready
document.addEventListener('DOMContentLoaded', () => {
    const tog = document.getElementById('toggle-budget');
    if (tog) tog.addEventListener('click', toggleBudget);
    const saveBtn = document.getElementById('budget-save-btn');
    if (saveBtn) saveBtn.addEventListener('click', saveBudgetAmount);
});

