import chalk from 'chalk';
import { getUsageSummary } from './cost-tracker.js';
import { formatDuration, formatTranscriptUserLine, theme } from './theme.js';
import { getCurrentVersion } from './updater.js';
const ANSI = {
    saveCursor: '\x1B7',
    restoreCursor: '\x1B8',
    scrollRegion: (top, bottom) => `\x1B[${top};${bottom}r`,
    resetScrollRegion: '\x1B[r',
    moveTo: (row, col) => `\x1B[${row};${col}H`,
    clearLine: '\x1B[2K',
};
const FOOTER_ROWS = 5;
const PROMPT_PREFIX = '> ';
const TEMPLATE_KEYS = [
    'provider',
    'model',
    'permissions',
    'session',
    'cwd',
    'workspace',
    'sandbox',
    'mode',
    'cost',
    'tokens',
    'sessioncost',
    'sessiontokens',
    'latency',
    'firsttoken',
    'turnlatency',
    'budget',
    'activity',
    'version',
];
let active = null;
let state = {
    provider: '',
    model: '',
    permissionMode: '',
    mode: 'dev',
    sessionId: '',
    sessionName: '',
    cwd: process.cwd(),
    sandbox: 'off',
    version: getCurrentVersion(),
    activity: 'Ready',
    activityStartedAtMs: null,
    activityFrame: 0,
    turn: 0,
    draft: '',
    lastCost: '$0.0000',
    lastTokens: '0 tokens',
    sessionCost: '$0.0000',
    sessionTokens: '0 tokens',
    lastFirstToken: '',
    lastTurnLatency: '',
    budget: '',
    acceptingPrompt: false,
};
let activityTicker = null;
export function shouldUseFixedFooter(config, env = process.env) {
    const raw = (env.GRAWKUS_FIXED_FOOTER || env.GRAWKUS_FOOTER || '').trim().toLowerCase();
    if (raw === '0' || raw === 'false' || raw === 'off' || raw === 'no')
        return false;
    if (env.GRAWKUS_NON_INTERACTIVE === '1')
        return false;
    if (config.footer?.enabled === false)
        return false;
    if (config.voice?.accessibility?.screenReader === true)
        return false;
    return true;
}
export function buildFooterSnapshot(config, mode, session, cwd) {
    return {
        provider: config.provider,
        model: config.model,
        permissionMode: config.permissionMode,
        mode,
        sessionId: session.id,
        sessionName: session.name,
        cwd,
        sandbox: config.sandbox?.level || 'off',
        template: config.footer?.template,
        version: getCurrentVersion(),
    };
}
export function activateFooter(snapshot) {
    Object.assign(state, snapshot);
    if (active) {
        resizeIfNeeded();
        syncActivityTicker();
        redraw();
        return true;
    }
    if (!process.stdout.isTTY)
        return false;
    const rows = process.stdout.rows || 0;
    const cols = process.stdout.columns || 0;
    if (rows < FOOTER_ROWS + 6 || cols < 40)
        return false;
    active = {
        rows,
        cols,
        scrollBottom: rows - FOOTER_ROWS,
        footerTop: rows - FOOTER_ROWS + 1,
    };
    process.stdout.write('\n');
    process.stdout.write(ANSI.scrollRegion(1, active.scrollBottom));
    process.stdout.write(ANSI.moveTo(active.scrollBottom, 1));
    syncActivityTicker();
    redraw();
    return true;
}
export function deactivateFooter() {
    if (!active)
        return;
    const current = active;
    process.stdout.write(ANSI.saveCursor);
    process.stdout.write(ANSI.resetScrollRegion);
    for (let row = current.footerTop; row <= current.rows; row++) {
        process.stdout.write(ANSI.moveTo(row, 1));
        process.stdout.write(ANSI.clearLine);
    }
    process.stdout.write(ANSI.restoreCursor);
    active = null;
    syncActivityTicker();
}
export function isFooterActive() {
    return active !== null;
}
export function updateFooter(snapshot) {
    Object.assign(state, snapshot);
    if (!active)
        return;
    resizeIfNeeded();
    syncActivityTicker();
    redraw();
}
export function setFooterActivity(activity, turn = state.turn, startedAtMs = state.activityStartedAtMs) {
    state.activity = activity || 'Ready';
    state.turn = turn;
    state.activityStartedAtMs = startedAtMs;
    state.activityFrame++;
    syncActivityTicker();
    if (active)
        redraw();
}
export function setFooterDraft(draft) {
    state.draft = draft;
    if (active && !state.acceptingPrompt)
        redraw();
}
export function setFooterCost(cost, promptTokens, completionTokens, details = {}) {
    const summary = safeUsageSummary(state.sessionId);
    const last = summary?.last;
    const firstTokenMs = finiteMs(details.firstTokenMs) ?? finiteMs(last?.firstTokenMs);
    const durationMs = finiteMs(details.durationMs) ?? finiteMs(last?.durationMs);
    const sessionCost = details.sessionCost ?? summary?.session.cost ?? cost;
    const sessionTokens = details.sessionTokens ?? summary?.session.tokens ?? (promptTokens + completionTokens);
    state.lastCost = `$${cost.toFixed(4)}`;
    state.lastTokens = `${formatTokenCount(promptTokens)}->${formatTokenCount(completionTokens)} tokens`;
    state.sessionCost = `$${sessionCost.toFixed(4)}`;
    state.sessionTokens = `${formatTokenCount(sessionTokens)} tokens`;
    state.lastFirstToken = firstTokenMs === undefined ? '' : formatLatency(firstTokenMs);
    state.lastTurnLatency = durationMs === undefined ? '' : formatLatency(durationMs);
    state.budget = formatBudget();
    if (active)
        redraw();
}
export function prepareFooterPrompt() {
    if (!active)
        return false;
    state.acceptingPrompt = true;
    state.draft = '';
    resizeIfNeeded();
    redraw(false);
    process.stdout.write(ANSI.moveTo(active.footerTop + 2, 1));
    process.stdout.write(ANSI.clearLine);
    return true;
}
export async function askWithFooterPrompt(rl, prefill = '', options = {}) {
    if (!prepareFooterPrompt()) {
        return rl.question(theme.prompt(PROMPT_PREFIX));
    }
    const echoSubmittedLine = options.echoSubmittedLine !== false;
    const answerPromise = rl.question(theme.prompt(PROMPT_PREFIX));
    if (prefill) {
        setImmediate(() => {
            const line = prefill.replace(/\r?\n/g, ' ');
            try {
                const rlAny = rl;
                if (typeof rlAny.write === 'function')
                    rlAny.write(line);
            }
            catch {
                process.stdout.write(line);
            }
        });
    }
    const answer = await answerPromise;
    finishFooterPrompt(answer, echoSubmittedLine);
    return answer;
}
function finishFooterPrompt(answer, echoSubmittedLine) {
    state.acceptingPrompt = false;
    state.draft = '';
    if (!active)
        return;
    if (echoSubmittedLine) {
        writeFooterSubmittedLine(answer);
    }
    else {
        process.stdout.write(ANSI.moveTo(active.scrollBottom, 1));
    }
    redraw();
}
export function writeFooterSubmittedLine(answer) {
    if (!active)
        return;
    const trimmed = answer.replace(/\r?\n/g, ' ');
    if (trimmed.trim()) {
        writeScrollableLine(formatTranscriptUserLine(trimmed, active.cols));
        return;
    }
    process.stdout.write(ANSI.moveTo(active.scrollBottom, 1));
}
export function writeScrollableLine(line) {
    if (!active) {
        process.stdout.write(line + '\n');
        return;
    }
    process.stdout.write(ANSI.moveTo(active.scrollBottom, 1));
    process.stdout.write(ANSI.clearLine);
    process.stdout.write(line + '\n');
}
function resizeIfNeeded() {
    if (!active || !process.stdout.isTTY)
        return;
    const rows = process.stdout.rows || active.rows;
    const cols = process.stdout.columns || active.cols;
    if (rows === active.rows && cols === active.cols)
        return;
    if (rows < FOOTER_ROWS + 6 || cols < 40) {
        deactivateFooter();
        return;
    }
    active = {
        rows,
        cols,
        scrollBottom: rows - FOOTER_ROWS,
        footerTop: rows - FOOTER_ROWS + 1,
    };
    process.stdout.write(ANSI.scrollRegion(1, active.scrollBottom));
}
function syncActivityTicker() {
    const shouldTick = active !== null && state.activityStartedAtMs !== null;
    if (shouldTick && !activityTicker) {
        activityTicker = setInterval(() => {
            if (!active || state.activityStartedAtMs === null) {
                syncActivityTicker();
                return;
            }
            state.activityFrame++;
            redraw();
        }, 500);
        // Keep referenced so elapsed/activity frames continue while awaiting
        // provider events; cleared immediately when activity ends.
    }
    else if (!shouldTick && activityTicker) {
        clearInterval(activityTicker);
        activityTicker = null;
    }
}
function redraw(restoreCursor = true) {
    if (!active)
        return;
    const lines = footerLines(active.cols);
    if (restoreCursor)
        process.stdout.write(ANSI.saveCursor);
    for (let i = 0; i < FOOTER_ROWS; i++) {
        process.stdout.write(ANSI.moveTo(active.footerTop + i, 1));
        process.stdout.write(ANSI.clearLine);
        process.stdout.write(lines[i] || '');
    }
    if (restoreCursor)
        process.stdout.write(ANSI.restoreCursor);
}
function footerLines(cols) {
    const status = state.template?.trim()
        ? renderTemplate(state.template)
        : `Provider ${state.provider}  |  Model ${state.model}  |  Permissions ${state.permissionMode}  |  Session ${sessionDisplay()}  |  v${state.version || getCurrentVersion()}`;
    const activity = renderActivity();
    const draft = state.draft.replace(/[\r\n]+/g, ' ');
    const prompt = state.acceptingPrompt
        ? ''
        : draft
            ? theme.prompt(PROMPT_PREFIX) + theme.command(clipAnsi(draft, Math.max(10, cols - PROMPT_PREFIX.length - 2))) + theme.prompt(' \u258a')
            : theme.prompt(PROMPT_PREFIX) + theme.prompt('\u258a ') + theme.dim('Type your message or @path/to/file');
    const columnWidths = footerColumnWidths(cols);
    const workspace = compactCwd(state.cwd);
    const sandbox = state.sandbox === 'off' ? 'no sandbox' : state.sandbox || 'no sandbox';
    const budget = state.budget || formatBudget();
    const latency = formatFooterLatency();
    const usageCore = `${state.sessionCost || '$0.0000'} | ${state.sessionTokens || '0 tokens'}`;
    const usage = [
        usageCore,
        latency,
        budget ? `budget ${budget}` : '',
    ].filter(Boolean).join(' | ');
    const labels = [
        'workspace',
        'sandbox',
        'mode',
        'cost/tokens',
    ];
    const values = [
        workspace.value,
        sandbox,
        state.mode,
        usage,
    ];
    return [
        theme.command(padLine(status, cols)),
        theme.command(padLine(`${activityGlyph()} ${activity}`, cols)),
        padLine(prompt, cols),
        theme.dim(joinColumns(labels, columnWidths, cols)),
        joinColumns([
            theme.primary(values[0]),
            state.sandbox === 'off' ? theme.warning(values[1]) : theme.success(values[1]),
            theme.command(values[2]),
            theme.cost(values[3]),
        ], columnWidths, cols),
    ];
}
function renderActivity() {
    if (state.activityStartedAtMs !== null) {
        const elapsed = Math.max(0, Date.now() - state.activityStartedAtMs);
        const detail = [
            formatDuration(elapsed),
            'Esc/F5 to interrupt',
            state.turn > 0 ? `turn ${state.turn}` : '',
        ].filter(Boolean).join(' • ');
        return `${state.activity} (${detail})`;
    }
    return state.activity || 'Ready';
}
function activityGlyph() {
    const frames = ['\u25dc', '\u25dd', '\u25de', '\u25df'];
    return state.activityStartedAtMs !== null ? frames[state.activityFrame % frames.length] : '\u25b6';
}
function renderTemplate(template) {
    const usage = getUsageSummary(state.sessionId);
    const latency = formatFooterLatency();
    const values = {
        provider: state.provider,
        model: state.model,
        permissions: state.permissionMode,
        session: sessionDisplay(),
        cwd: state.cwd,
        workspace: compactCwd(state.cwd).value,
        sandbox: state.sandbox === 'off' ? 'no sandbox' : state.sandbox || 'no sandbox',
        mode: state.mode,
        cost: state.lastCost,
        tokens: state.lastTokens,
        sessioncost: state.sessionCost,
        sessiontokens: state.sessionTokens,
        latency,
        firsttoken: state.lastFirstToken,
        turnlatency: state.lastTurnLatency,
        budget: usage.budget.monthlyLimit > 0 ? `$${usage.budget.monthlyLimit}` : '',
        activity: renderActivity(),
        version: state.version || getCurrentVersion(),
    };
    return template.replace(/\{([a-z]+)\}/gi, (_match, key) => {
        const normalized = key.toLowerCase();
        return normalized in values ? values[normalized] : `{${key}}`;
    });
}
function safeUsageSummary(sessionId) {
    try {
        return getUsageSummary(sessionId);
    }
    catch {
        return null;
    }
}
function formatBudget() {
    try {
        const usage = getUsageSummary();
        if (usage.budget.monthlyLimit > 0)
            return `$${usage.budget.monthlyLimit}`;
        if (usage.budget.dailyLimit > 0)
            return `$${usage.budget.dailyLimit}/day`;
    }
    catch {
        // best effort only
    }
    return '';
}
function formatTokenCount(n) {
    return n > 999 ? `${(n / 1000).toFixed(1)}K` : String(n);
}
function finiteMs(value) {
    return typeof value === 'number' && Number.isFinite(value) && value >= 0
        ? value
        : undefined;
}
function formatLatency(ms) {
    return ms >= 1000 ? `${(ms / 1000).toFixed(1)}s` : `${Math.round(ms)}ms`;
}
function formatFooterLatency() {
    const bits = [];
    if (state.lastFirstToken)
        bits.push(`first ${state.lastFirstToken}`);
    if (state.lastTurnLatency)
        bits.push(`turn ${state.lastTurnLatency}`);
    return bits.join(' | ');
}
function sessionDisplay() {
    const name = (state.sessionName || '').trim();
    if (!name)
        return state.sessionId;
    return name.replace(/^Session\s+/i, '').trim() || name;
}
function footerColumnWidths(cols) {
    const side = Math.max(10, Math.min(18, Math.floor(cols * 0.17)));
    const last = cols - side * 3;
    if (last >= 10)
        return [side, side, side, last];
    const equal = Math.max(8, Math.floor(cols / 4));
    return [equal, equal, equal, Math.max(8, cols - equal * 3)];
}
function compactCwd(cwd) {
    const home = process.env.USERPROFILE || process.env.HOME || '';
    const normalized = home && cwd.toLowerCase().startsWith(home.toLowerCase())
        ? '~' + cwd.slice(home.length)
        : cwd;
    const parts = normalized.split(/[\\/]+/).filter(Boolean);
    const value = normalized === '~' ? '~' : parts.length > 0 ? parts.slice(-2).join('/') : normalized;
    return {
        label: value.length > 20 ? value.slice(0, 19) + '\u2026' : value,
        value: value || '~',
    };
}
function joinColumns(values, columnWidths, cols) {
    const widths = Array.isArray(columnWidths)
        ? columnWidths
        : values.map(() => columnWidths);
    return padLine(values.map((value, index) => {
        const width = widths[index] ?? widths.at(-1) ?? 12;
        return visiblePad(clipAnsi(value, width), width);
    }).join(''), cols);
}
function padLine(value, cols) {
    const plainLength = visibleLength(value);
    const clipped = plainLength > cols ? clipAnsi(value, cols) : value;
    return clipped + ' '.repeat(Math.max(0, cols - visibleLength(clipped)));
}
function visiblePad(value, width) {
    return value + ' '.repeat(Math.max(0, width - visibleLength(value)));
}
function visibleLength(value) {
    return value.replace(/\x1b\[[0-9;]*m/g, '').length;
}
function clipAnsi(value, width) {
    const plain = value.replace(/\x1b\[[0-9;]*m/g, '');
    if (plain.length <= width)
        return value;
    const clipped = plain.slice(0, Math.max(0, width - 1)) + '\u2026';
    return chalk.reset(clipped);
}
//# sourceMappingURL=fixed-footer.js.map