import { suggestArchivableSpecs, archiveSpecToPath } from '../context-manager.js';
import { writeCheckpoint } from '../session/checkpoint-writer.js';
import { sessionTracker } from '../session/session-tracker.js';
import { specStore } from '../../storage/index.js';
import { hashProjectPath, projectDataDir } from '../../storage/base-store.js';
import { emitAutopilotEvent } from '../autopilot/event-bus.js';
const WARN_THRESHOLD = 80;
const CRITICAL_THRESHOLD = 90;
const ARCHIVE_AFTER_DAYS = 7;
const TOKENS_PER_SPEC = 1500;
const ARCHIVE_SUBDIR = 'archived-context';
function archiveFilePath(projectId, specId) {
    return `${projectDataDir(projectId)}/${ARCHIVE_SUBDIR}/${specId}.json`;
}
/** Returns usage percent (0-100) given current and max tokens. */
export function detectContextPressure(currentTokens, maxTokens) {
    if (maxTokens <= 0) {
        return 0;
    }
    return Math.min(100, Math.round((currentTokens / maxTokens) * 100));
}
/**
 * Executes the automatic context relief pipeline when usage is at or above 80%.
 *
 * - 80-89%: archive done specs >7d old + create session checkpoint
 * - >=90%: also compresses spec history marker + emits context:pressure event
 * - disabled=true: returns warning only, no actions executed
 */
export async function runReliefPipeline(usagePercent, projectPath, options) {
    const projectId = hashProjectPath(projectPath);
    const maxTokens = 200_000; // standard context window
    const currentTokens = Math.round((usagePercent / 100) * maxTokens);
    const availableTokens = Math.max(0, maxTokens - currentTokens);
    if (usagePercent < WARN_THRESHOLD) {
        return {
            usagePercent,
            availableTokens,
            freedTokens: 0,
            actionsExecuted: [],
            warning: '',
        };
    }
    const warning = buildWarning(usagePercent, availableTokens);
    if (options.disabled) {
        return {
            usagePercent,
            availableTokens,
            freedTokens: 0,
            actionsExecuted: [],
            warning,
        };
    }
    const actionsExecuted = [];
    let freedTokens = 0;
    // Step 1: Archive done specs updated more than 7 days ago
    const archivedCount = await archiveDoneSpecs(projectId, projectPath, actionsExecuted);
    freedTokens += archivedCount * TOKENS_PER_SPEC;
    // Step 2: Create session checkpoint
    await createSessionCheckpoint(projectPath, actionsExecuted);
    // Step 3: At 90%+ also compress spec history and emit event
    if (usagePercent >= CRITICAL_THRESHOLD) {
        actionsExecuted.push('compress_spec_history (marker recorded)');
        emitAutopilotEvent({
            name: 'context:pressure',
            projectPath,
            projectId,
            payload: { usagePercent, freedTokens },
        });
        actionsExecuted.push('context:pressure event emitted');
    }
    const newUsedTokens = Math.max(0, currentTokens - freedTokens);
    const newAvailableTokens = Math.max(0, maxTokens - newUsedTokens);
    const newPercent = detectContextPressure(newUsedTokens, maxTokens);
    return {
        usagePercent: newPercent,
        availableTokens: newAvailableTokens,
        freedTokens,
        actionsExecuted,
        warning: buildPostReliefSummary(usagePercent, newPercent, freedTokens, actionsExecuted),
    };
}
// ---------------------------------------------------------------------------
// Internal helpers
// ---------------------------------------------------------------------------
async function archiveDoneSpecs(projectId, projectPath, actionsExecuted) {
    try {
        const specs = await specStore.listSpecs(projectId);
        const suggestion = suggestArchivableSpecs(specs, ARCHIVE_AFTER_DAYS);
        if (suggestion.specs.length === 0) {
            return 0;
        }
        let archived = 0;
        for (const candidate of suggestion.specs) {
            const spec = specs.find((s) => s.id === candidate.specId);
            if (!spec) {
                continue;
            }
            const archPath = archiveFilePath(projectId, candidate.specId);
            await archiveSpecToPath(archPath, spec);
            archived++;
        }
        if (archived > 0) {
            actionsExecuted.push(`archive_spec_context: ${String(archived)} spec(s) archived`);
        }
        void projectPath; // used via projectId
        return archived;
    }
    catch {
        // Non-critical — do not fail the pipeline
        return 0;
    }
}
async function createSessionCheckpoint(projectPath, actionsExecuted) {
    try {
        const snapshot = sessionTracker.getSnapshot();
        await writeCheckpoint(projectPath, snapshot);
        actionsExecuted.push('session_checkpoint: written to planu/session-context.md');
    }
    catch {
        // Non-critical — do not fail the pipeline
    }
}
function buildWarning(usagePercent, availableTokens) {
    const level = usagePercent >= CRITICAL_THRESHOLD ? 'CRITICAL' : 'WARNING';
    const actions = [
        '1. Run `optimize_context` to review archivable specs',
        '2. Use `session_checkpoint` to save current progress',
        '3. Delegate remaining work to subagents (haiku/sonnet)',
    ];
    return [
        `[Context ${level}] ${String(usagePercent)}% used — ${String(availableTokens)} tokens remaining`,
        '',
        'Suggested actions:',
        ...actions,
    ].join('\n');
}
function buildPostReliefSummary(beforePercent, afterPercent, freedTokens, actionsExecuted) {
    return [
        `Context relief applied: ${String(beforePercent)}% → ${String(afterPercent)}% used`,
        `Freed ~${String(freedTokens)} tokens`,
        `Actions executed: ${actionsExecuted.join(', ')}`,
    ].join('\n');
}
//# sourceMappingURL=index.js.map