"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createResumeCreateCommand = createResumeCreateCommand;
exports.createResumeInspectCommand = createResumeInspectCommand;
exports.createResumeResumeCommand = createResumeResumeCommand;
exports.createResumeClearCommand = createResumeClearCommand;
exports.createResumeCleanupCommand = createResumeCleanupCommand;
const errors_1 = require("../../../lib/errors");
const agent_context_1 = require("../../../lib/agent-context");
const output_1 = require("../../../lib/output");
const resume_capsule_1 = require("../../../lib/resume-capsule");
const work_selection_1 = require("../../../lib/work-selection");
const runtime_contract_1 = require("../../../lib/runtime/runtime-contract");
async function createResumeCreateCommand() {
    const { Command } = await import('commander');
    return new Command('create')
        .description('Create or explicitly replace an evidence-backed user-local resume capsule.')
        .requiredOption('--artifact <path>', 'Repository-relative selected planning artifact.')
        .option('--session <name>', 'Named local session. Defaults to default.')
        .option('--completed-action <id...>', 'Historical completed action ids to record.')
        .option('--evidence <path...>', 'Repository-relative evidence paths to hash.')
        .option('--postcondition <path...>', 'Repository-relative postcondition evidence paths to hash.')
        .option('--blocker <text...>', 'Unresolved blocker evidence to preserve.')
        .option('--expires-in-hours <hours>', 'Positive expiry in hours. Defaults to 24.')
        .option('--if-match <token>', 'Opaque token from resume inspect; required to replace existing state.')
        .action((options, commandInstance) => {
        const root = repositoryRoot(commandInstance);
        const context = (0, agent_context_1.createArtifactAgentContext)({
            repositoryRoot: root,
            artifactPath: options.artifact,
            session: options.session,
            detail: 'compact',
        });
        const result = (0, resume_capsule_1.createResumeCapsule)({
            repositoryRoot: root,
            artifactPath: context.selection.artifactPath,
            session: options.session,
            completedActionIds: options.completedAction,
            evidencePaths: options.evidence,
            postconditionPaths: options.postcondition,
            unresolvedBlockers: options.blocker,
            nextAction: context.recommendedNextAction,
            expiresInMs: parseExpiry(options.expiresInHours),
            ifMatch: options.ifMatch,
        });
        emit('resume create', commandInstance, result, true, 'Resume capsule updated');
    });
}
async function createResumeInspectCommand() {
    const { Command } = await import('commander');
    return new Command('inspect')
        .description('Inspect capsule freshness without writing capsule or selection state.')
        .option('--artifact <path>', 'Explicit artifact identity for conflict checking.')
        .option('--session <name>', 'Named local session. Defaults to default.')
        .action((options, commandInstance) => {
        const root = repositoryRoot(commandInstance);
        const selection = (0, work_selection_1.inspectWorkSelection)({ repositoryRoot: root, session: options.session });
        const result = (0, resume_capsule_1.inspectResumeCapsule)({
            repositoryRoot: root,
            session: options.session,
            explicitArtifactPath: options.artifact,
            selectedArtifactPath: selection.state === 'fresh' ? selection.selection?.artifactPath : null,
        });
        emit('resume inspect', commandInstance, {
            ...result,
            readOnly: true,
            noWriteBoundary: 'Inspection does not create, refresh, replace, clear, or clean capsule or selection state.',
        }, false, 'Resume capsule inspection');
    });
}
async function createResumeResumeCommand() {
    const { Command } = await import('commander');
    return new Command('resume')
        .description('Revalidate a capsule and report the currently permitted next action without writing state.')
        .option('--artifact <path>', 'Explicit artifact identity; takes precedence and conflicts fail closed.')
        .option('--session <name>', 'Named local session. Defaults to default.')
        .action((options, commandInstance) => {
        const root = repositoryRoot(commandInstance);
        const selection = (0, work_selection_1.inspectWorkSelection)({ repositoryRoot: root, session: options.session });
        const inspection = (0, resume_capsule_1.resumeFromCapsule)({
            repositoryRoot: root,
            session: options.session,
            explicitArtifactPath: options.artifact,
            selectedArtifactPath: selection.state === 'fresh' ? selection.selection?.artifactPath : null,
        });
        assertResumable(inspection);
        const context = (0, agent_context_1.createArtifactAgentContext)({
            repositoryRoot: root,
            artifactPath: inspection.capsule.artifactPath,
            session: options.session,
            detail: 'compact',
        });
        emit('resume resume', commandInstance, {
            ...inspection,
            currentNextAction: context.recommendedNextAction,
            currentNextActionResolution: context.workEvidence?.nextAction ?? null,
            currentBasicWorkflow: context.workEvidence?.basicWorkflow ?? null,
            currentBlockers: context.relevantBlockers,
            recordedNextActionMatches: inspection.capsule.nextAction.id === context.recommendedNextAction.id,
            recordedResolverResultAvailable: false,
            authorityBoundary: 'Recorded capsule actions and transcript-like evidence cannot authorize the current action; canonical evidence is re-resolved on every resume.',
            readOnly: true,
            noWriteBoundary: 'Resume revalidates canonical evidence and reports current action legality without changing capsule or selection state.',
        }, false, 'Resume capsule is fresh');
    });
}
async function createResumeClearCommand() {
    const { Command } = await import('commander');
    return new Command('clear')
        .description('Clear one named resume capsule explicitly.')
        .option('--session <name>', 'Named local session. Defaults to default.')
        .option('--if-match <token>', 'Opaque token from resume inspect; required when state exists.')
        .action((options, commandInstance) => emit('resume clear', commandInstance, (0, resume_capsule_1.clearResumeCapsule)({ repositoryRoot: repositoryRoot(commandInstance), ...options }), true, 'Resume capsule clear'));
}
async function createResumeCleanupCommand() {
    const { Command } = await import('commander');
    return new Command('cleanup')
        .description('Clear one stale or expired capsule while preserving fresh or absent state.')
        .option('--session <name>', 'Named local session. Defaults to default.')
        .option('--if-match <token>', 'Opaque token from resume inspect; required to clear stale state.')
        .action((options, commandInstance) => emit('resume cleanup', commandInstance, (0, resume_capsule_1.cleanupResumeCapsule)({ repositoryRoot: repositoryRoot(commandInstance), ...options }), true, 'Resume capsule cleanup'));
}
function assertResumable(value) {
    if (value.state === 'fresh')
        return;
    if (value.state === 'conflict') {
        throw new errors_1.RuntimeError({
            code: 'RESUME_SELECTION_CONFLICT',
            exitCode: errors_1.RuntimeExitCode.CONCURRENCY_CONFLICT,
            message: 'Resume capsule conflicts with current explicit or selected artifact evidence.',
            details: [
                `Capsule artifact: ${value.capsule?.artifactPath}`,
                `Current artifact: ${value.conflict?.explicitArtifactPath}`,
                'No capsule or selection state was changed.',
            ],
            recoveryActions: [
                (0, errors_1.createDescriptorBackedRecoveryAction)({
                    command: 'resume clear',
                    argv: ['day-shift', 'resume', 'clear', '--session', value.session, '--if-match', value.preconditionToken],
                    explanation: 'Clear the conflicting capsule explicitly after reviewing current evidence.',
                }),
            ],
        });
    }
    if (value.state === 'stale') {
        throw new errors_1.RuntimeError({
            code: 'RESUME_CAPSULE_STALE',
            exitCode: errors_1.RuntimeExitCode.STALE_EVIDENCE,
            message: 'Resume capsule evidence is stale and cannot prove action completion.',
            details: [
                `Reason: ${value.staleReason}`,
                'Completed action ids were suppressed. No capsule or selection state was changed.',
            ],
            recoveryActions: [
                (0, errors_1.createDescriptorBackedRecoveryAction)({
                    command: 'resume cleanup',
                    argv: ['day-shift', 'resume', 'cleanup', '--session', value.session, '--if-match', value.preconditionToken],
                    explanation: 'Clear stale capsule state after reviewing current evidence.',
                }),
            ],
        });
    }
    throw new errors_1.RuntimeError({
        code: 'RESUME_CAPSULE_MISSING',
        exitCode: errors_1.RuntimeExitCode.USAGE,
        message: 'No resume capsule is available for this session.',
        details: ['Create a capsule from an explicit artifact and current workflow evidence. No state was changed.'],
        recoveryActions: [
            (0, errors_1.createNonCallableRecoveryAction)({
                id: 'recovery.create-resume-capsule',
                command: 'resume create',
                explanation: 'Create a capsule for the intended artifact.',
                reason: 'No authoritative artifact value is available for exact create argv.',
            }),
        ],
    });
}
function parseExpiry(value) {
    if (value === undefined)
        return undefined;
    const hours = Number(value);
    if (!Number.isFinite(hours) || hours <= 0)
        throw (0, errors_1.createUsageError)('--expires-in-hours must be a positive number.');
    return Math.round(hours * 60 * 60 * 1000);
}
function emit(command, commandInstance, data, write, heading) {
    const format = (0, output_1.resolveOutputFormat)(commandInstance.optsWithGlobals?.().format);
    if (format === null)
        throw (0, errors_1.createUsageError)('Output format must be one of: text, json.');
    (0, output_1.emitSuccess)({
        command,
        format,
        data: write ? { ...data, stateSurface: 'user-local resume capsule' } : data,
        text: [
            heading,
            `Session: ${data.session}`,
            `State: ${data.state ?? data.reason ?? 'updated'}`,
            (0, output_1.renderTerminalBoundary)(write
                ? {
                    kind: data.changed === false ? 'mutating-no-op' : 'write-applied',
                    reason: data.changed === false ? data.reason : undefined,
                    target: data.session,
                    stateSurface: 'user-local resume capsule',
                }
                : { kind: 'read-only' }),
        ].join('\n'),
    });
}
function repositoryRoot(commandInstance) {
    const root = (commandInstance?.parent?.parent ?? commandInstance);
    return (root?.configRepositoryContext ?? (0, runtime_contract_1.createRepositoryContext)((0, runtime_contract_1.detectRepositoryRoot)(), false)).root;
}
