import { spawn } from "node:child_process";
import { getConfig, modelToBackend } from "./config.js";
const EMPTY_BACKEND = {
    inputTokens: 0,
    outputTokens: 0,
    totalTokens: 0,
    totalCost: 0,
    modelsUsed: [],
};
function emptyBackends() {
    return {
        "claude-code": { ...EMPTY_BACKEND },
        codex: { ...EMPTY_BACKEND },
        cursorai: { ...EMPTY_BACKEND },
    };
}
function num(x) {
    if (typeof x === "number" && !Number.isNaN(x))
        return x;
    if (typeof x === "string")
        return Number.parseFloat(x) || 0;
    return 0;
}
function aggregateEntry(entry, backends, config) {
    const inT = num(entry.inputTokens);
    const outT = num(entry.outputTokens);
    const totalT = num(entry.totalTokens) || inT + outT;
    const cost = num(entry.totalCost ?? entry.costUSD);
    const models = entry.modelsUsed ?? entry.models ?? [];
    if (models.length === 0 && entry.breakdown) {
        for (const m of Object.keys(entry.breakdown))
            models.push(m);
    }
    if (models.length === 0) {
        // No per-model info: attribute all to first backend (or spread later); treat as "unknown" and skip or put in first
        const fallback = config.priority[0];
        const b = backends[fallback];
        b.inputTokens += inT;
        b.outputTokens += outT;
        b.totalTokens += totalT;
        b.totalCost += cost;
        return;
    }
    if (entry.breakdown && typeof entry.breakdown === "object") {
        for (const [model, stats] of Object.entries(entry.breakdown)) {
            const backend = modelToBackend(model, config) ?? modelToBackend("anthropic", config) ?? config.priority[0];
            const bb = backends[backend];
            bb.inputTokens += num(stats.inputTokens);
            bb.outputTokens += num(stats.outputTokens);
            bb.totalTokens += num(stats.totalTokens);
            bb.totalCost += num(stats.costUSD ?? stats.totalCost);
            if (!bb.modelsUsed.includes(model))
                bb.modelsUsed.push(model);
        }
        return;
    }
    // No breakdown: split evenly across models, then map each model to backend
    const perModelCost = models.length ? cost / models.length : 0;
    const perModelTokens = models.length ? totalT / models.length : 0;
    const perModelIn = models.length ? inT / models.length : 0;
    const perModelOut = models.length ? outT / models.length : 0;
    for (const model of models) {
        const backend = modelToBackend(model, config) ?? modelToBackend("anthropic", config) ?? config.priority[0];
        const b = backends[backend];
        b.inputTokens += perModelIn;
        b.outputTokens += perModelOut;
        b.totalTokens += perModelTokens;
        b.totalCost += perModelCost;
        if (!b.modelsUsed.includes(model))
            b.modelsUsed.push(model);
    }
}
/** Run @ccusage/pi CLI and return usage aggregated by backend. */
export async function getUsage(period = "daily") {
    const config = getConfig();
    const backends = emptyBackends();
    const piPath = process.env.PI_AGENT_DIR;
    const args = [
        "@ccusage/pi@latest",
        period,
        "--json",
        "--breakdown",
    ];
    if (piPath)
        args.push("--pi-path", piPath);
    return new Promise((resolve) => {
        const child = spawn("npx", args, {
            stdio: ["ignore", "pipe", "pipe"],
            shell: true,
            env: { ...process.env, ...(piPath ? { PI_AGENT_DIR: piPath } : {}) },
        });
        let stdout = "";
        let stderr = "";
        child.stdout?.setEncoding("utf-8");
        child.stdout?.on("data", (chunk) => { stdout += chunk; });
        child.stderr?.setEncoding("utf-8");
        child.stderr?.on("data", (chunk) => { stderr += chunk; });
        child.on("error", (err) => {
            resolve({
                backends,
                totals: { inputTokens: 0, outputTokens: 0, totalTokens: 0, totalCost: 0 },
                period,
                error: `Failed to run @ccusage/pi: ${err.message}. Is npx available and @ccusage/pi installed?`,
            });
        });
        child.on("close", (code) => {
            if (code !== 0) {
                resolve({
                    backends,
                    totals: { inputTokens: 0, outputTokens: 0, totalTokens: 0, totalCost: 0 },
                    period,
                    error: stderr.trim() || `@ccusage/pi exited with code ${code}. Run: npx @ccusage/pi@latest ${period} --json --breakdown`,
                });
                return;
            }
            let data;
            try {
                data = JSON.parse(stdout);
            }
            catch {
                resolve({
                    backends,
                    totals: { inputTokens: 0, outputTokens: 0, totalTokens: 0, totalCost: 0 },
                    period,
                    error: "Invalid JSON from @ccusage/pi. Ensure --json is supported by your @ccusage/pi version.",
                });
                return;
            }
            const entries = data.daily ?? data.data ?? (data.projects ? [].concat(...Object.values(data.projects).filter(Array.isArray)) : []);
            for (const entry of entries)
                aggregateEntry(entry, backends, config);
            const totals = (data.totals ?? data.summary) ?? {};
            const totalInput = Object.values(backends).reduce((s, b) => s + b.inputTokens, 0);
            const totalOutput = Object.values(backends).reduce((s, b) => s + b.outputTokens, 0);
            const totalTokens = Object.values(backends).reduce((s, b) => s + b.totalTokens, 0);
            const totalCost = Object.values(backends).reduce((s, b) => s + b.totalCost, 0);
            resolve({
                backends,
                totals: {
                    inputTokens: totalInput || num(totals["inputTokens"] ?? totals["totalInputTokens"]),
                    outputTokens: totalOutput || num(totals["outputTokens"] ?? totals["totalOutputTokens"]),
                    totalTokens: totalTokens || num(totals["totalTokens"]),
                    totalCost: totalCost || num(totals["totalCost"] ?? totals["totalCostUSD"]),
                },
                period,
            });
        });
    });
}
//# sourceMappingURL=usage.js.map