/**
 * Footer status renderer for skill proposals. Subscribes to the proposal
 * status channel and formats each phase as a single line. Transient phases
 * (error, updated-with-message) auto-clear back to the pending count after a
 * short timeout so the footer doesn't get stuck on stale messages.
 */
import stripAnsi from 'strip-ansi';
import { tryCountSkillProposals } from '../../app/skill-proposals/catalog.js';
import { getSkillProposalRoots } from '../../app/skill-proposals/proposal-fs.js';
import { emitSkillProposalStatus, subscribeSkillProposalStatus } from '../../app/skill-proposals/status.js';
import { formatToolCallStatus } from './tool-call-status.js';
const STATUS_KEY = 'proposals';
const TRANSIENT_STATUS_MS = 12000;
const MAX_ERROR_MESSAGE_CHARS = 80;
/** Format the steady-state pending-proposal count, or undefined when nothing is pending. */
function proposalCountText(count) {
    if (count <= 0)
        return undefined;
    const label = count === 1 ? '1 skill proposal pending' : `${count} skill proposals pending`;
    return `${label} - ↓ to manage`;
}
/** Strip control characters and ellipsize a status message to fit the footer width. */
function truncateStatusMessage(message) {
    const normalized = stripAnsi(message)
        .replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, '')
        .replace(/\s+/g, ' ')
        .trim();
    if (normalized.length <= MAX_ERROR_MESSAGE_CHARS)
        return normalized;
    return `${normalized.slice(0, MAX_ERROR_MESSAGE_CHARS - 1)}…`;
}
/** Format a skill-proposal status event into the one-line text shown in the footer. */
function formatStatus(status) {
    switch (status.phase) {
        case 'running':
            return formatToolCallStatus('Skill proposal', status.toolCall);
        case 'checked':
            return proposalCountText(status.count);
        case 'updated':
            return status.message
                ? `Skill proposal: updated - ${truncateStatusMessage(status.message)}`
                : proposalCountText(status.count);
        case 'error':
            return `Skill proposal: error - ${truncateStatusMessage(status.message)}`;
    }
}
/** Re-emit the current proposal count so the footer status reflects the on-disk truth. */
export function refreshSkillProposalStatus(roots = getSkillProposalRoots()) {
    const result = tryCountSkillProposals(roots);
    emitSkillProposalStatus('message' in result
        ? { phase: 'error', count: 0, message: result.message }
        : { phase: 'checked', count: result.count });
}
/** Start subscribing to skill-proposal status events; returns a teardown function. */
export function startSkillProposalStatusUpdater(setStatus, requestRender, roots = getSkillProposalRoots()) {
    let clearTimer = null;
    const setCount = () => {
        const result = tryCountSkillProposals(roots);
        setStatus(STATUS_KEY, 'message' in result
            ? `Skill proposal: error - ${truncateStatusMessage(result.message)}`
            : proposalCountText(result.count));
        requestRender();
    };
    const unsubscribe = subscribeSkillProposalStatus((status) => {
        if (clearTimer) {
            clearTimeout(clearTimer);
            clearTimer = null;
        }
        setStatus(STATUS_KEY, formatStatus(status));
        requestRender();
        if (status.phase === 'error' || (status.phase === 'updated' && status.message)) {
            clearTimer = setTimeout(() => {
                clearTimer = null;
                setCount();
            }, TRANSIENT_STATUS_MS);
            clearTimer.unref();
        }
    });
    setCount();
    return () => {
        unsubscribe();
        if (clearTimer)
            clearTimeout(clearTimer);
        setStatus(STATUS_KEY, undefined);
        requestRender();
    };
}
//# sourceMappingURL=skill-proposals-status.js.map