/**
 * Append-only spend ledger (issue #346).
 *
 * Every dispatched run that produces token usage records one JSONL line under
 * `<history>/spend/ledger.jsonl`. The ledger is the shared artifact #323's
 * `agents insights cost` can later read for $ rollups, so the entry shape stays clean
 * and stable: one record = one usage observation attributed to a run.
 *
 * `costUsd` is computed at write time via the canonical pricing module
 * (lib/pricing) so the ledger is self-contained — a reader never needs the
 * pricing table to sum spend. Rollups (`spendForDay`/`spendForAgent`/...) are
 * pure folds over the file; for the modest line counts a developer accrues this
 * is plenty fast, and there's no index to corrupt.
 */
import * as fs from 'fs';
import * as path from 'path';
import { getHistoryDir } from '../state.js';
import { actualCost } from '../pricing/index.js';
/** Default ledger path: <history>/spend/ledger.jsonl. */
export function defaultLedgerPath() {
    return path.join(getHistoryDir(), 'spend', 'ledger.jsonl');
}
/** Local YYYY-MM-DD for a Date (defaults to now). Local, not UTC — caps are a human-day notion. */
export function localDay(d = new Date()) {
    const y = d.getFullYear();
    const m = String(d.getMonth() + 1).padStart(2, '0');
    const day = String(d.getDate()).padStart(2, '0');
    return `${y}-${m}-${day}`;
}
/**
 * Append one spend observation. Computes `costUsd` from the usage via the
 * canonical pricing module (unpriced models contribute $0). Returns the written
 * entry. Creates the spend dir on first write.
 */
export function recordSpend(input, ledgerPath = defaultLedgerPath()) {
    const ts = input.ts ?? new Date();
    const cacheTok = (input.usage.cacheReadTokens ?? 0) + (input.usage.cacheCreationTokens ?? 0);
    const { usd } = actualCost(input.model, {
        inputTokens: input.usage.inputTokens ?? 0,
        outputTokens: input.usage.outputTokens ?? 0,
        cacheReadTokens: input.usage.cacheReadTokens,
        cacheCreationTokens: input.usage.cacheCreationTokens,
    });
    const entry = {
        runId: input.runId,
        agent: input.agent,
        project: input.project ?? '',
        day: localDay(ts),
        model: input.model,
        inputTok: input.usage.inputTokens ?? 0,
        outputTok: input.usage.outputTokens ?? 0,
        cacheTok,
        costUsd: usd,
        source: input.source,
        ts: ts.toISOString(),
    };
    fs.mkdirSync(path.dirname(ledgerPath), { recursive: true });
    fs.appendFileSync(ledgerPath, JSON.stringify(entry) + '\n');
    return entry;
}
/** Load every entry. Skips malformed lines (a half-written final line never breaks a rollup). */
export function loadLedger(ledgerPath = defaultLedgerPath()) {
    if (!fs.existsSync(ledgerPath))
        return [];
    const out = [];
    for (const line of fs.readFileSync(ledgerPath, 'utf-8').split('\n')) {
        const trimmed = line.trim();
        if (!trimmed)
            continue;
        try {
            const parsed = JSON.parse(trimmed);
            if (typeof parsed.costUsd === 'number')
                out.push(parsed);
        }
        catch {
            // Tolerate a torn final line; everything before it is intact.
        }
    }
    return out;
}
function sum(entries, pred) {
    let total = 0;
    for (const e of entries)
        if (pred(e))
            total += e.costUsd;
    return total;
}
/** Total USD spend on a given local day across ALL agents (cross-vendor). */
export function spendForDay(day, ledger = loadLedger()) {
    return sum(ledger, (e) => e.day === day);
}
/** Total USD spend on a given day for ONE agent (per-agent cap accounting). */
export function spendForAgentDay(agent, day, ledger = loadLedger()) {
    return sum(ledger, (e) => e.agent === agent && e.day === day);
}
/** Total USD spend attributed to an agent across all time. */
export function spendForAgent(agent, ledger = loadLedger()) {
    return sum(ledger, (e) => e.agent === agent);
}
/** Total USD spend attributed to a project across all time (cross-vendor). */
export function spendForProject(project, ledger = loadLedger()) {
    return sum(ledger, (e) => e.project === project);
}
/** Total USD spend for a single run id (all of its usage observations). */
export function spendForRun(runId, ledger = loadLedger()) {
    return sum(ledger, (e) => e.runId === runId);
}
