import { truncateToWidth, visibleWidth, } from "@earendil-works/pi-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`;
}
function replaceHome(input) {
    const home = process.env.HOME || process.env.USERPROFILE;
    if (home && input.startsWith(home)) {
        return `~${input.slice(home.length)}`;
    }
    return input;
}
function rightAlign(line, width) {
    const lineWidth = visibleWidth(line);
    if (lineWidth >= width) {
        return truncateToWidth(line, width, theme.fg("dim", "..."));
    }
    return `${" ".repeat(width - lineWidth)}${line}`;
}
function getUsageLine(session, autoCompactEnabled, width) {
    const state = 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 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 = session.getContextUsage();
    const contextWindow = contextUsage?.contextWindow ?? state.model?.contextWindow ?? 0;
    const contextPercentValue = contextUsage?.percent ?? 0;
    const contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : "?";
    const usageParts = [];
    if (totalInput)
        usageParts.push(`${theme.fg("dim", "↑")}${theme.fg("muted", formatTokens(totalInput))}`);
    if (totalOutput)
        usageParts.push(`${theme.fg("dim", "↓")}${theme.fg("muted", formatTokens(totalOutput))}`);
    if (totalCacheRead)
        usageParts.push(`${theme.fg("dim", "R")}${theme.fg("muted", formatTokens(totalCacheRead))}`);
    if (totalCacheWrite)
        usageParts.push(`${theme.fg("dim", "W")}${theme.fg("muted", formatTokens(totalCacheWrite))}`);
    // Show cost with "(sub)" indicator if using OAuth subscription
    const usingSubscription = state.model
        ? session.modelRegistry.isUsingOAuth(state.model)
        : false;
    if (totalCost || usingSubscription) {
        usageParts.push(`${theme.fg("muted", `$${totalCost.toFixed(3)}`)}${usingSubscription ? ` ${theme.fg("dim", "(sub)")}` : ""}`);
    }
    const autoIndicator = autoCompactEnabled ? " (auto)" : "";
    const contextPercentDisplay = contextPercent === "?"
        ? `?/${formatTokens(contextWindow)}${autoIndicator}`
        : `${contextPercent}%/${formatTokens(contextWindow)}${autoIndicator}`;
    if (contextPercentValue > 90) {
        usageParts.push(theme.fg("error", contextPercentDisplay));
    }
    else if (contextPercentValue > 70) {
        usageParts.push(theme.fg("warning", contextPercentDisplay));
    }
    else {
        usageParts.push(theme.fg("muted", contextPercentDisplay));
    }
    const separator = theme.fg("dim", " • ");
    const usageText = usageParts.length > 0
        ? usageParts.join(separator)
        : theme.fg("muted", contextPercentDisplay);
    return rightAlign(usageText, width);
}
/**
 * Right-aligned usage meter that sits above the composer, matching the approved
 * prototype's separate token/cost/context ribbon.
 */
export class UsageMeterComponent {
    constructor(session) {
        this.session = session;
        this.autoCompactEnabled = true;
    }
    setSession(session) {
        this.session = session;
    }
    setAutoCompactEnabled(enabled) {
        this.autoCompactEnabled = enabled;
    }
    invalidate() {
        // Render pulls live session data.
    }
    render(width) {
        return [getUsageLine(this.session, this.autoCompactEnabled, width)];
    }
}
/**
 * Sparse statusline below the composer. It mirrors the preview: model + cwd
 * when idle, or one semantic dot with short recovery copy while work is live.
 */
export class FooterComponent {
    constructor(session, footerData) {
        this.session = session;
        this.footerData = footerData;
    }
    setSession(session) {
        this.session = session;
    }
    setAutoCompactEnabled(_enabled) {
        // Usage state lives in UsageMeterComponent. Kept for compatibility with existing call sites.
    }
    /**
     * 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;
        const pwd = replaceHome(this.session.sessionManager.getCwd());
        const modelName = state.model?.id || "no-model";
        let modelLabel = modelName;
        if (state.model?.reasoning) {
            const thinkingLevel = state.thinkingLevel || "off";
            modelLabel =
                thinkingLevel === "off" ? modelName : `${modelName} ${thinkingLevel}`;
        }
        if (this.footerData.getAvailableProviderCount() > 1 && state.model) {
            modelLabel = `(${state.model.provider}) ${modelLabel}`;
        }
        const liveState = this.session.isStreaming
            ? theme.fg("muted", "Esc to interrupt")
            : undefined;
        const statusText = liveState ??
            `${theme.fg("dim", modelLabel)} ${theme.fg("dim", "•")} ${theme.fg("muted", pwd)}`;
        return [truncateToWidth(statusText, width, theme.fg("dim", "..."))];
    }
}
//# sourceMappingURL=footer.js.map