"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createWorkSelectCommand = createWorkSelectCommand;
exports.createWorkCurrentCommand = createWorkCurrentCommand;
exports.createWorkNextCommand = createWorkNextCommand;
exports.createWorkClearCommand = createWorkClearCommand;
exports.createWorkCleanupCommand = createWorkCleanupCommand;
const errors_1 = require("../../../lib/errors");
const output_1 = require("../../../lib/output");
const planning_navigation_1 = require("../../../lib/planning/planning-navigation");
const work_selection_1 = require("../../../lib/work-selection");
const runtime_contract_1 = require("../../../lib/runtime/runtime-contract");
async function createWorkSelectCommand() {
    const { Command } = await import("commander");
    return new Command("select")
        .description("Persist one explicit planning artifact in a user-local named work session.")
        .requiredOption("--artifact <path>", "Repository-relative planning artifact to select.")
        .option("--session <name>", "Named local session. Defaults to default.")
        .option("--intent <text>", "Bounded provenance for why the selection was established.")
        .option("--if-match <token>", "Opaque token from work current; required to replace existing session state.")
        .action((options, commandInstance) => {
        const format = requireFormat(commandInstance);
        const repositoryContext = resolveRepositoryContext(commandInstance);
        const result = (0, work_selection_1.selectWorkArtifact)({
            repositoryRoot: repositoryContext.root,
            artifactPath: options.artifact,
            session: options.session,
            intent: options.intent,
            ifMatch: options.ifMatch
        });
        (0, output_1.emitSuccess)({
            command: "work select",
            format,
            data: { ...result, writeApplied: true, stateSurface: "user-local work selection" },
            text: [
                "Work selection updated",
                `Session: ${result.session}`,
                `Artifact: ${result.selection?.artifactPath ?? "(none)"}`,
                `Revision: ${result.storeRevision}`,
                (0, output_1.renderTerminalBoundary)({ kind: "write-applied", target: result.session, stateSurface: "user-local work selection" })
            ].join("\n")
        });
    });
}
async function createWorkCurrentCommand() {
    const { Command } = await import("commander");
    return new Command("current")
        .description("Inspect current named work selection and freshness without writing state.")
        .option("--session <name>", "Named local session. Defaults to default.")
        .action((options, commandInstance) => {
        const format = requireFormat(commandInstance);
        const repositoryContext = resolveRepositoryContext(commandInstance);
        const result = (0, work_selection_1.inspectWorkSelection)({ repositoryRoot: repositoryContext.root, ...options });
        (0, output_1.emitSuccess)({
            command: "work current",
            format,
            data: { ...result, readOnly: true, noWriteBoundary: "Current inspection does not create, refresh, or clear selection state." },
            text: [
                "Current work selection",
                `Session: ${result.session}`,
                `State: ${result.state}`,
                `Artifact: ${result.selection?.artifactPath ?? "(none)"}`,
                `Stale reason: ${result.staleReason ?? "(none)"}`,
                (0, output_1.renderTerminalBoundary)({ kind: "read-only" })
            ].join("\n")
        });
    });
}
async function createWorkNextCommand() {
    const { Command } = await import("commander");
    return new Command("next")
        .description("Resolve explicit or stored work selection and report its next action without writing state.")
        .option("--artifact <path>", "Explicit repository-relative planning artifact for this invocation.")
        .option("--session <name>", "Named local session. Defaults to default.")
        .action((options, commandInstance) => {
        const format = requireFormat(commandInstance);
        const repositoryContext = resolveRepositoryContext(commandInstance);
        const resolution = (0, work_selection_1.resolveWorkSelection)({
            repositoryRoot: repositoryContext.root,
            explicitArtifactPath: options.artifact,
            session: options.session
        });
        assertResolvedSelection(resolution);
        const nextAction = (0, planning_navigation_1.suggestPlanningNextAction)({
            repositoryRoot: repositoryContext.root,
            artifactPath: resolution.artifactPath
        });
        (0, output_1.emitSuccess)({
            command: "work next",
            format,
            data: {
                resolution,
                nextAction,
                readOnly: true,
                noWriteBoundary: "Next-action resolution does not create, refresh, replace, or clear selection state."
            },
            text: [
                "Selected work next action",
                `Selection source: ${resolution.source}`,
                `Artifact: ${resolution.artifactPath}`,
                `Recommendation: ${nextAction.recommendation}`,
                `Command: ${nextAction.command ?? "(workflow-guided step)"}`,
                (0, output_1.renderTerminalBoundary)({ kind: "read-only" })
            ].join("\n")
        });
    });
}
async function createWorkClearCommand() {
    const { Command } = await import("commander");
    return new Command("clear")
        .description("Clear one named user-local work selection session.")
        .option("--session <name>", "Named local session. Defaults to default.")
        .option("--if-match <token>", "Opaque token from work current; required when the session exists.")
        .action((options, commandInstance) => {
        const format = requireFormat(commandInstance);
        const repositoryContext = resolveRepositoryContext(commandInstance);
        const result = (0, work_selection_1.clearWorkSelection)({ repositoryRoot: repositoryContext.root, ...options });
        (0, output_1.emitSuccess)({
            command: "work clear",
            format,
            data: { ...result, writeApplied: result.changed, noOp: !result.changed, stateSurface: "user-local work selection" },
            text: [
                result.changed ? "Work selection cleared" : "Work selection already absent",
                `Session: ${result.session}`,
                `Revision: ${result.storeRevision}`,
                (0, output_1.renderTerminalBoundary)(result.changed
                    ? { kind: "write-applied", target: result.session, stateSurface: "user-local work selection" }
                    : { kind: "mutating-no-op", reason: "The selected session had no stored work selection.", target: result.session, stateSurface: "user-local work selection" })
            ].join("\n")
        });
    });
}
async function createWorkCleanupCommand() {
    const { Command } = await import("commander");
    return new Command("cleanup")
        .description("Clear one stale named work selection while preserving fresh or absent state.")
        .option("--session <name>", "Named local session. Defaults to default.")
        .option("--if-match <token>", "Opaque token from work current; required to clear stale state.")
        .action((options, commandInstance) => {
        const format = requireFormat(commandInstance);
        const repositoryContext = resolveRepositoryContext(commandInstance);
        const result = (0, work_selection_1.cleanupStaleWorkSelection)({ repositoryRoot: repositoryContext.root, ...options });
        (0, output_1.emitSuccess)({
            command: "work cleanup",
            format,
            data: { ...result, writeApplied: result.changed, noOp: !result.changed, stateSurface: "user-local work selection" },
            text: [
                result.changed ? "Stale work selection cleared" : "Work selection cleanup made no change",
                `Session: ${result.session}`,
                `Reason: ${result.reason}`,
                `Revision: ${result.storeRevision}`,
                (0, output_1.renderTerminalBoundary)(result.changed
                    ? { kind: "write-applied", target: result.session, stateSurface: "user-local work selection" }
                    : { kind: "mutating-no-op", reason: result.reason, target: result.session, stateSurface: "user-local work selection" })
            ].join("\n")
        });
    });
}
function assertResolvedSelection(resolution) {
    if (resolution.status === "resolved")
        return;
    if (resolution.status === "conflict") {
        throw new errors_1.RuntimeError({
            code: "WORK_SELECTION_CONFLICT",
            exitCode: errors_1.RuntimeExitCode.CONCURRENCY_CONFLICT,
            message: "Explicit artifact input conflicts with the active stored work selection.",
            details: [
                `Explicit artifact: ${resolution.conflict?.explicitArtifactPath}`,
                `Stored artifact: ${resolution.conflict?.storedArtifactPath}`,
                "No selection state was changed. Clear or replace the stored session explicitly, then retry."
            ],
            recoveryActions: [(0, errors_1.createDescriptorBackedRecoveryAction)({
                    command: "work clear",
                    argv: ["day-shift", "work", "clear", "--session", resolution.session],
                    explanation: "Clear the conflicting stored selection explicitly, then rerun with the intended artifact."
                })]
        });
    }
    if (resolution.status === "stale") {
        throw new errors_1.RuntimeError({
            code: "WORK_SELECTION_STALE",
            exitCode: errors_1.RuntimeExitCode.STALE_EVIDENCE,
            message: "Stored work selection evidence is stale.",
            details: [`Reason: ${resolution.staleReason}`, "No selection state was changed. Run work select again with current artifact evidence."],
            recoveryActions: [
                (0, errors_1.createDescriptorBackedRecoveryAction)({
                    command: "work current",
                    argv: ["day-shift", "work", "current", "--session", resolution.session, "--format", "json"],
                    explanation: "Refresh the current selection freshness and precondition evidence without writing state."
                }),
                (0, errors_1.createDescriptorBackedRecoveryAction)({
                    command: "work cleanup",
                    argv: [
                        "day-shift", "work", "cleanup", "--session", resolution.session,
                        "--if-match", resolution.preconditionToken, "--format", "json"
                    ],
                    explanation: "Clear the stale stored selection using the current precondition token."
                })
            ]
        });
    }
    throw new errors_1.RuntimeError({
        code: "WORK_SELECTION_MISSING",
        exitCode: errors_1.RuntimeExitCode.USAGE,
        message: "No work selection is available for next-action resolution.",
        details: ["Pass --artifact for this invocation or run work select explicitly. No selection state was changed."],
        recoveryActions: [(0, errors_1.createDescriptorBackedRecoveryAction)({
                command: "work candidates",
                argv: ["day-shift", "work", "candidates", "--max-results", "5", "--format", "json", "--detail", "compact"],
                explanation: "List a bounded set of planning candidates before selecting an artifact explicitly."
            })]
    });
}
function requireFormat(commandInstance) {
    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.");
    return format;
}
function resolveRepositoryContext(commandInstance) {
    const rootCommand = commandInstance?.parent?.parent ?? commandInstance;
    if (rootCommand?.configRepositoryContext)
        return rootCommand.configRepositoryContext;
    return (0, runtime_contract_1.createRepositoryContext)((0, runtime_contract_1.detectRepositoryRoot)(), false);
}
