import { truncateToWidth, visibleWidth } from "@operator/tui";
import { theme } from "../theme/theme.js";
/**
 * Sanitize text for display in a single-line status.
 * Removes newlines, tabs, carriage returns, and other control characters.
 */
function sanitizeStatusText(text) {
    // Replace newlines, tabs, carriage returns with space, then collapse multiple spaces
    return text
        .replace(/[\r\n\t]/g, " ")
        .replace(/ +/g, " ")
        .trim();
}
/**
 * Format token counts (similar to web-ui)
 */
function formatTokens(count) {
    if (count < 1000)
        return count.toString();
    if (count < 10000)
        return `${(count / 1000).toFixed(1)}k`;
    if (count < 1000000)
        return `${Math.round(count / 1000)}k`;
    if (count < 10000000)
        return `${(count / 1000000).toFixed(1)}M`;
    return `${Math.round(count / 1000000)}M`;
}
/**
 * Footer component that shows pwd, token stats, and context usage.
 * Computes token/context stats from session, gets git branch and extension statuses from provider.
 */
export class FooterComponent {
    session;
    footerData;
    autoCompactEnabled = true;
    constructor(session, footerData) {
        this.session = session;
        this.footerData = footerData;
    }
    setSession(session) {
        this.session = session;
    }
    setAutoCompactEnabled(enabled) {
        this.autoCompactEnabled = enabled;
    }
    /**
     * No-op: git branch caching now handled by provider.
     * Kept for compatibility with existing call sites in interactive-mode.
     */
    invalidate() {
        // No-op: git branch is cached/invalidated by provider
    }
    /**
     * Clean up resources.
     * Git watcher cleanup now handled by provider.
     */
    dispose() {
        // Git watcher cleanup handled by provider
    }
    render(width) {
        const state = this.session.state;
        // Calculate cumulative usage from ALL session entries (not just post-compaction messages)
        let totalInput = 0;
        let totalOutput = 0;
        let totalCacheRead = 0;
        let totalCacheWrite = 0;
        let totalCost = 0;
        for (const entry of this.session.sessionManager.getEntries()) {
            if (entry.type === "message" && entry.message.role === "assistant") {
                totalInput += entry.message.usage.input;
                totalOutput += entry.message.usage.output;
                totalCacheRead += entry.message.usage.cacheRead;
                totalCacheWrite += entry.message.usage.cacheWrite;
                totalCost += entry.message.usage.cost.total;
            }
        }
        // Calculate context usage from session (handles compaction correctly).
        // After compaction, tokens are unknown until the next LLM response.
        const contextUsage = this.session.getContextUsage();
        const contextWindow = contextUsage?.contextWindow ?? state.model?.contextWindow ?? 0;
        const contextPercentValue = contextUsage?.percent ?? 0;
        const contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : "?";
        // Replace home directory with ~
        let pwd = this.session.sessionManager.getCwd();
        const home = process.env.HOME || process.env.USERPROFILE;
        if (home && pwd.startsWith(home)) {
            pwd = `~${pwd.slice(home.length)}`;
        }
        // Add git branch if available
        const branch = this.footerData.getGitBranch();
        if (branch) {
            pwd = `${pwd} (${branch})`;
        }
        // Add session name if set
        const sessionName = this.session.sessionManager.getSessionName();
        if (sessionName) {
            pwd = `${pwd} • ${sessionName}`;
        }
        // Build usage line
        const statsParts = [];
        if (totalInput)
            statsParts.push(`↑${formatTokens(totalInput)}`);
        if (totalOutput)
            statsParts.push(`↓${formatTokens(totalOutput)}`);
        if (totalCacheRead)
            statsParts.push(`R${formatTokens(totalCacheRead)}`);
        if (totalCacheWrite)
            statsParts.push(`W${formatTokens(totalCacheWrite)}`);
        // Show cost with "(sub)" indicator if using OAuth subscription
        const usingSubscription = state.model ? this.session.modelRegistry.isUsingOAuth(state.model) : false;
        if (totalCost || usingSubscription) {
            const costStr = `$${totalCost.toFixed(3)}${usingSubscription ? " (sub)" : ""}`;
            statsParts.push(costStr);
        }
        // Colorize context percentage based on usage
        let contextPercentStr;
        const autoIndicator = this.autoCompactEnabled ? " (auto)" : "";
        const contextPercentDisplay = contextPercent === "?"
            ? `?/${formatTokens(contextWindow)}${autoIndicator}`
            : `${contextPercent}%/${formatTokens(contextWindow)}${autoIndicator}`;
        if (contextPercentValue > 90) {
            contextPercentStr = theme.fg("error", contextPercentDisplay);
        }
        else if (contextPercentValue > 70) {
            contextPercentStr = theme.fg("warning", contextPercentDisplay);
        }
        else {
            contextPercentStr = contextPercentDisplay;
        }
        statsParts.push(contextPercentStr);
        let statsLeft = statsParts.join("  ");
        const modelName = state.model?.id || "no-model";
        let rightSideWithoutProvider = modelName;
        if (state.model?.reasoning) {
            const thinkingLevel = state.thinkingLevel || "off";
            rightSideWithoutProvider =
                thinkingLevel === "off" ? `${modelName} | reasoning fast` : `${modelName} | reasoning ${thinkingLevel}`;
        }
        const providerName = state.model?.provider || "none";
        const sessionValue = sessionName || "unnamed";
        const sessionId = this.session.sessionManager.getSessionId() ||
            this.session.sessionManager
                .getSessionFile()
                ?.match(/_([0-9a-f-]+)\.jsonl$/)?.[1] ||
            undefined;
        const shortSessionId = sessionId ? sessionId.slice(0, 8) : undefined;
        const projectLine = truncateToWidth(theme.fg("accent", "PROJECT DECK  ") +
            theme.fg("text", pwd) +
            theme.fg("dim", "  •  thread ") +
            theme.fg("text", sessionValue) +
            (shortSessionId ? theme.fg("dim", "  •  ") + theme.fg("text", shortSessionId) : ""), width, theme.fg("dim", "..."));
        const runtimeLine = truncateToWidth(theme.fg("accent", "RUNTIME DECK  ") +
            theme.fg("text", rightSideWithoutProvider) +
            theme.fg("dim", "  •  engine ") +
            theme.fg("text", providerName), width, theme.fg("dim", "..."));
        const telemetryLine = truncateToWidth(theme.fg("accent", "TELEMETRY     ") +
            theme.fg("dim", "context ") +
            contextPercentStr +
            theme.fg("dim", "  •  usage ") +
            theme.fg("text", statsLeft || "idle"), width, theme.fg("dim", "..."));
        const lines = [projectLine, runtimeLine, telemetryLine];
        // Add extension statuses on a single line, sorted by key alphabetically
        const extensionStatuses = this.footerData.getExtensionStatuses();
        if (extensionStatuses.size > 0) {
            const sortedStatuses = Array.from(extensionStatuses.entries())
                .sort(([a], [b]) => a.localeCompare(b))
                .map(([, text]) => sanitizeStatusText(text));
            const statusLine = theme.fg("accent", "PACKAGES      ") + theme.fg("text", sortedStatuses.join("  |  "));
            lines.push(truncateToWidth(statusLine, width, theme.fg("dim", "...")));
        }
        return lines;
    }
}
//# sourceMappingURL=footer.js.map
