import { existsSync } from "fs";
import { readdir, readFile } from "fs/promises";
import { join } from "path";
import { getSessionsDir } from "../config.js";
/**
 * Parse a session filename timestamp back to a Date.
 * Filename timestamps look like "2026-04-09T18-49-11-406Z" (colons and dots replaced with hyphens).
 * Returns null if the timestamp doesn't match the expected format.
 */
export function filenameTimestampToDate(fileTimestamp) {
    // fileTimestamp like "2026-04-09T18-49-11-406Z"
    // Reconstruct: YYYY-MM-DDThh:mm:ss.mmmZ
    const match = fileTimestamp.match(/^(\d{4}-\d{2}-\d{2})T(\d{2})-(\d{2})-(\d{2})-(\d{3})Z$/);
    if (!match)
        return null;
    const iso = `${match[1]}T${match[2]}:${match[3]}:${match[4]}.${match[5]}Z`;
    const date = new Date(iso);
    return Number.isNaN(date.getTime()) ? null : date;
}
/**
 * Check if two dates fall on the same local calendar day.
 */
export function isSameLocalDay(date, today) {
    return (date.getFullYear() === today.getFullYear() &&
        date.getMonth() === today.getMonth() &&
        date.getDate() === today.getDate());
}
/**
 * Tracks aggregate cost across all sessions for the current calendar day.
 * Scans session files filtered by filename timestamp, caches result for O(1) footer access.
 * Refreshes periodically (60s) and on-demand via refresh().
 */
export class DailyCostTracker {
    static REFRESH_INTERVAL_MS = 60_000;
    cachedCost = 0;
    refreshTimer = null;
    disposed = false;
    sessionsDir;
    constructor(sessionsDir) {
        this.sessionsDir = sessionsDir ?? getSessionsDir();
        // Kick off initial async scan — getDailyCost() returns 0 until it completes
        void this.initialScan();
    }
    /** Get cached daily cost total. O(1). */
    getDailyCost() {
        return this.cachedCost;
    }
    /** Force an async refresh of the daily cost. */
    async refresh() {
        if (!this.disposed) {
            const cost = await this.scanDailyCost();
            if (!this.disposed) {
                this.cachedCost = cost;
            }
        }
    }
    /** Clean up timer and prevent in-flight scans from updating cache. */
    dispose() {
        this.disposed = true;
        if (this.refreshTimer) {
            clearTimeout(this.refreshTimer);
            this.refreshTimer = null;
        }
    }
    async initialScan() {
        const cost = await this.scanDailyCost();
        if (!this.disposed) {
            this.cachedCost = cost;
            this.scheduleNextRefresh();
        }
    }
    scheduleNextRefresh() {
        if (this.disposed)
            return;
        this.refreshTimer = setTimeout(async () => {
            this.refreshTimer = null;
            if (this.disposed)
                return;
            const cost = await this.scanDailyCost();
            if (!this.disposed) {
                this.cachedCost = cost;
                this.scheduleNextRefresh();
            }
        }, DailyCostTracker.REFRESH_INTERVAL_MS);
        // Allow the timer to not keep the process alive
        if (this.refreshTimer && typeof this.refreshTimer === "object" && "unref" in this.refreshTimer) {
            this.refreshTimer.unref();
        }
    }
    async scanDailyCost() {
        try {
            if (!existsSync(this.sessionsDir))
                return 0;
            const now = new Date();
            let total = 0;
            const projectDirs = await readdir(this.sessionsDir, { withFileTypes: true });
            for (const dirEntry of projectDirs) {
                if (!dirEntry.isDirectory())
                    continue;
                const projectDir = join(this.sessionsDir, dirEntry.name);
                let files;
                try {
                    files = (await readdir(projectDir)).filter((f) => f.endsWith(".jsonl"));
                }
                catch {
                    /* Directory unreadable — skip this session dir */
                    continue;
                }
                for (const filename of files) {
                    // Extract timestamp part: everything before the UUID
                    // Filename: 2026-04-09T18-49-11-406Z_33137d5d-d1e4-4a0e-baca-ebd08ab0e2e0.jsonl
                    const underscoreIdx = filename.indexOf("_", 20);
                    if (underscoreIdx === -1)
                        continue;
                    const timestampPart = filename.slice(0, underscoreIdx);
                    const fileDate = filenameTimestampToDate(timestampPart);
                    if (!fileDate)
                        continue;
                    // Skip sessions not from today (compares local calendar day)
                    if (!isSameLocalDay(fileDate, now))
                        continue;
                    // Read and parse the JSONL file
                    total += await this.sumCostFromFile(join(projectDir, filename));
                }
            }
            return total;
        }
        catch {
            // Never crash the app
            return 0;
        }
    }
    async sumCostFromFile(filePath) {
        try {
            const content = await readFile(filePath, "utf8");
            let total = 0;
            for (const line of content.split("\n")) {
                if (!line.trim())
                    continue;
                try {
                    const entry = JSON.parse(line);
                    if (entry.type === "message" && entry.message?.role === "assistant") {
                        total += entry.message.usage?.cost?.total ?? 0;
                    }
                }
                catch {
                    // Skip malformed lines
                }
            }
            return total;
        }
        catch {
            /* File unreadable — treat as zero cost */
            return 0;
        }
    }
}
//# sourceMappingURL=daily-cost-tracker.js.map