"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createVersionCommand = createVersionCommand;
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const errors_1 = require("../../../lib/errors");
const output_1 = require("../../../lib/output");
const command_contract_1 = require("../../../lib/version-manager/command-contract");
const doctor_1 = require("../../../lib/version-manager/doctor");
const license_resolution_1 = require("../../../lib/license/license-resolution");
const runtime_contract_1 = require("../../../lib/runtime/runtime-contract");
const install_1 = require("../../../lib/version-manager/install");
const selection_1 = require("../../../lib/version-manager/selection");
const state_layout_1 = require("../../../lib/version-manager/state-layout");
const uninstall_1 = require("../../../lib/version-manager/uninstall");
const global_format_1 = require("../global-format");
const registration_1 = require("../registration");
async function createVersionCommand() {
    const { Command } = await import("commander");
    const command = new Command("version");
    command
        .description("Manage installed Day Shift CLI versions through the existing day-shift command.")
        .addHelpText("after", [
        "",
        "Version manager boundary:",
        "  Manager operations are owned by day-shift version ... .",
        "  Normal day-shift invocations remain separate from this command family.",
        "  Install, selection, uninstall, and network availability behavior is introduced across later version-manager phases.",
        "",
        "Declared subcommands:",
        ...command_contract_1.VERSION_MANAGER_SUBCOMMANDS.map((name) => `  ${name}`)
    ].join("\n"));
    (0, registration_1.registerCommand)(command, createInstallCommand(Command));
    (0, registration_1.registerCommand)(command, createListCommand(Command));
    (0, registration_1.registerCommand)(command, createUseCommand(Command));
    (0, registration_1.registerCommand)(command, createPinCommand(Command));
    (0, registration_1.registerCommand)(command, createCurrentCommand(Command));
    (0, registration_1.registerCommand)(command, createUninstallCommand(Command));
    (0, registration_1.registerCommand)(command, createDoctorCommand(Command));
    (0, registration_1.registerCommand)(command, createCheckCommand(Command));
    (0, registration_1.registerCommand)(command, createAliasCommand(Command));
    return command;
}
function createInstallCommand(Command) {
    const command = new Command("install");
    command
        .description("Install a local Day Shift package source into version-manager state.")
        .option("--from <path>", "Local release archive or unpacked package root.")
        .option("--assert-version <version>", "Assert the exact package version before installing.")
        .action((...actionArgs) => {
        const commandInstance = actionArgs.at(-1);
        const options = commandInstance.opts();
        if (typeof options.from !== "string" || options.from.trim() === "") {
            throw (0, errors_1.createUsageError)("Version install requires --from <path>.", [
                "Recovery: rerun with a local .tar.gz, .zip, or unpacked package root."
            ]);
        }
        const requestedFormat = commandInstance.optsWithGlobals?.().format ?? (0, global_format_1.getGlobalFormat)(commandInstance);
        const format = (0, output_1.resolveOutputFormat)(requestedFormat);
        if (format === null) {
            throw (0, errors_1.createUnsupportedOutputFormatError)({
                received: requestedFormat,
                commandBoundary: "version install command output format"
            });
        }
        let result;
        try {
            result = (0, install_1.installManagedVersion)({
                sourcePath: options.from,
                assertedVersion: typeof options.assertVersion === "string" ? options.assertVersion : undefined,
                env: process.env
            });
        }
        catch (error) {
            throw (0, errors_1.createUsageError)("Version install source validation failed.", [
                error instanceof Error ? error.message : String(error),
                "No managed version state was mutated after validation failure."
            ]);
        }
        (0, output_1.emitSuccess)({
            command: "version install",
            format,
            text: renderVersionInstallResult(result),
            data: result
        });
        getRootCommand(commandInstance ?? command).runtimeExitCode = errors_1.RuntimeExitCode.SUCCESS;
    });
    return command;
}
function createDeferredSubcommand(Command, name, options) {
    const command = new Command(name);
    command.description(options.description);
    if (options.argument !== undefined) {
        command.argument(options.argument);
    }
    command.action((...actionArgs) => {
        const commandInstance = actionArgs.at(-1);
        emitVersionContract(commandInstance ?? command, (0, command_contract_1.createDeferredVersionCommandContract)({
            command: `version ${name}`,
            operation: options.operation
        }));
    });
    return command;
}
function renderVersionInstallResult(result) {
    return (0, output_1.renderTerminalSection)({
        heading: "Day Shift version install",
        headingStyle: "title",
        fields: [
            { label: "Version", value: result.version },
            { label: "Version manager root", value: result.versionManagerRoot },
            { label: "Managed package", value: result.managedPackageDirectory },
            { label: "Metadata", value: result.metadataPath },
            { label: "Receipt", value: result.receiptPath },
            { label: "Replaced existing package", value: result.replacedExistingPackage },
            { label: "Checksum status", value: result.checksumStatus },
            { label: "Network attempted", value: result.networkAttempted }
        ]
    });
}
function createListCommand(Command) {
    const command = new Command("list");
    command
        .description("List locally installed Day Shift versions with offline license summaries.")
        .action((...actionArgs) => {
        const commandInstance = actionArgs.at(-1);
        const requestedFormat = commandInstance.optsWithGlobals?.().format ?? (0, global_format_1.getGlobalFormat)(commandInstance);
        const format = (0, output_1.resolveOutputFormat)(requestedFormat);
        if (format === null) {
            throw (0, errors_1.createUnsupportedOutputFormatError)({
                received: requestedFormat,
                commandBoundary: "version list command output format"
            });
        }
        const result = listManagedVersions({
            env: process.env
        });
        (0, output_1.emitSuccess)({
            command: "version list",
            format,
            text: renderVersionListResult(result),
            data: result
        });
        getRootCommand(commandInstance ?? command).runtimeExitCode = errors_1.RuntimeExitCode.SUCCESS;
    });
    return command;
}
function listManagedVersions(options) {
    const versionManagerRoot = (0, state_layout_1.resolveVersionManagerRoot)({ env: options.env });
    const repositoryContext = (0, runtime_contract_1.createRepositoryContext)((0, runtime_contract_1.detectRepositoryRoot)(), false);
    const installedVersions = (0, selection_1.listInstalledVersions)(versionManagerRoot).map((installedVersion) => {
        const licenseStatus = (0, license_resolution_1.resolveLicenseStatus)({
            repositoryContext,
            env: options.env,
            currentCliVersion: installedVersion.version
        });
        return {
            ...installedVersion,
            license: {
                effective_status: licenseStatus.effective_status,
                reason_code: licenseStatus.reason_code,
                covered_release_line: licenseStatus.covered_release_line,
                current_version_coverage_state: licenseStatus.current_version_coverage_state,
                effective_coverage_path: licenseStatus.effective_coverage_path,
                license_path: licenseStatus.license_path
            }
        };
    });
    return {
        versionManagerRoot,
        installedVersions,
        count: installedVersions.length,
        networkAttempted: false,
        readOnly: true
    };
}
function renderVersionListResult(result) {
    return [
        (0, output_1.renderTerminalSection)({
            heading: "Day Shift version list",
            headingStyle: "title",
            fields: [
                { label: "Version manager root", value: result.versionManagerRoot },
                { label: "Installed versions", value: result.count },
                { label: "Network attempted", value: result.networkAttempted },
                { label: "Read only", value: result.readOnly }
            ]
        }),
        (0, output_1.renderTerminalCompactList)({
            heading: "Installed versions",
            headingStyle: "section",
            entries: result.installedVersions.map((entry) => ({
                label: entry.version,
                fields: [
                    { label: "Version directory", value: entry.versionDirectory },
                    { label: "Package", value: entry.packageDirectory },
                    { label: "License status", value: entry.license.effective_status },
                    { label: "License reason", value: entry.license.reason_code },
                    { label: "Covered release line", value: entry.license.covered_release_line },
                    { label: "Coverage state", value: entry.license.current_version_coverage_state },
                    { label: "Coverage path", value: entry.license.effective_coverage_path },
                    { label: "License path", value: entry.license.license_path }
                ]
            })),
            emptyMessage: "(none)"
        }),
        (0, output_1.renderTerminalBoundary)({ kind: "read-only" })
    ].join("\n\n");
}
function createUninstallCommand(Command) {
    const command = new Command("uninstall");
    command
        .description("Uninstall one managed Day Shift version.")
        .argument("[version]")
        .option("--replace-with <version>", "Replace affected selectors with another exact installed version before uninstalling.")
        .option("--confirm-selected-removal", "Confirm uninstall even when selectors point at the removed version.")
        .action((version, ...actionArgs) => {
        const commandInstance = actionArgs.at(-1);
        const options = commandInstance.opts();
        const requestedFormat = commandInstance.optsWithGlobals?.().format ?? (0, global_format_1.getGlobalFormat)(commandInstance);
        const format = (0, output_1.resolveOutputFormat)(requestedFormat);
        if (format === null) {
            throw (0, errors_1.createUnsupportedOutputFormatError)({
                received: requestedFormat,
                commandBoundary: "version uninstall command output format"
            });
        }
        const result = (0, uninstall_1.uninstallManagedVersion)({
            target: version,
            env: process.env,
            cwd: process.cwd(),
            replacementVersion: typeof options.replaceWith === "string" ? options.replaceWith : undefined,
            confirmSelectedRemoval: options.confirmSelectedRemoval === true
        });
        if (!result.ok) {
            emitVersionUninstallValidationFailure({
                commandInstance,
                command,
                format,
                result
            });
            return;
        }
        (0, output_1.emitSuccess)({
            command: "version uninstall",
            format,
            text: renderVersionUninstallResult(result),
            data: result
        });
        getRootCommand(commandInstance ?? command).runtimeExitCode = errors_1.RuntimeExitCode.SUCCESS;
    });
    return command;
}
function emitVersionUninstallValidationFailure(options) {
    (0, output_1.emitError)({
        command: "version uninstall",
        format: options.format,
        code: "USAGE_ERROR",
        message: options.result.message,
        details: options.result.details,
        data: options.result
    });
    getRootCommand(options.commandInstance ?? options.command).runtimeExitCode = errors_1.RuntimeExitCode.USAGE;
}
function renderVersionUninstallResult(result) {
    return [
        (0, output_1.renderTerminalSection)({
            heading: "Day Shift version uninstall",
            headingStyle: "title",
            fields: [
                { label: "Target version", value: result.target },
                { label: "Version manager root", value: result.versionManagerRoot },
                { label: "Version directory", value: result.versionDirectory },
                { label: "Removed version directory", value: result.removedVersionDirectory },
                { label: "Receipts directory", value: result.receiptsDirectory },
                { label: "Replacement version", value: result.replacementVersion ?? "(none)" },
                { label: "Replacement applied", value: result.replacementApplied },
                { label: "Confirmed selected removal", value: result.confirmedSelectedRemoval },
                { label: "Written", value: result.written }
            ]
        }),
        (0, output_1.renderTerminalCompactList)({
            heading: "Affected selectors",
            headingStyle: "section",
            entries: result.affectedSelectors.map((selector) => ({
                label: selector.label,
                fields: [
                    { label: "Kind", value: selector.kind },
                    { label: "Selector", value: selector.selector },
                    { label: "Path", value: selector.path }
                ]
            })),
            emptyMessage: "(none)"
        }),
        (0, output_1.renderTerminalPathBlock)({
            heading: "Removed receipts",
            headingStyle: "section",
            paths: result.removedReceiptPaths,
            emptyMessage: "(none)"
        }),
        (0, output_1.renderTerminalPathBlock)({
            heading: "Preserved receipts",
            headingStyle: "section",
            paths: result.preservedReceiptPaths,
            emptyMessage: "(none)"
        }),
        (0, output_1.renderTerminalCompactList)({
            heading: "Preserved state",
            headingStyle: "section",
            entries: result.preservedState.map((entry) => ({ label: entry })),
            emptyMessage: "(none)"
        }),
        (0, output_1.renderTerminalBoundary)({
            kind: "write-applied",
            target: result.versionDirectory,
            targetLabel: "Managed version directory",
            stateSurface: "version-manager managed package state"
        })
    ].join("\n\n");
}
function createCurrentCommand(Command) {
    const command = new Command("current");
    command
        .description("Show the currently selected Day Shift version.")
        .action((...actionArgs) => {
        const commandInstance = actionArgs.at(-1);
        const requestedFormat = commandInstance.optsWithGlobals?.().format ?? (0, global_format_1.getGlobalFormat)(commandInstance);
        const format = (0, output_1.resolveOutputFormat)(requestedFormat);
        if (format === null) {
            throw (0, errors_1.createUnsupportedOutputFormatError)({
                received: requestedFormat,
                commandBoundary: "version current command output format"
            });
        }
        const selection = (0, selection_1.resolveManagedVersionSelection)({
            env: process.env,
            cwd: process.cwd()
        });
        const result = {
            ...selection,
            readOnly: true,
            networkAttempted: false
        };
        (0, output_1.emitSuccess)({
            command: "version current",
            format,
            text: renderVersionCurrentResult(result),
            data: result
        });
        getRootCommand(commandInstance ?? command).runtimeExitCode = result.ok
            ? errors_1.RuntimeExitCode.SUCCESS
            : errors_1.RuntimeExitCode.ERROR;
    });
    return command;
}
function createPinCommand(Command) {
    const command = new Command("pin");
    command
        .description("Write a repository Day Shift version pin.")
        .argument("<version>")
        .action((version, ...actionArgs) => {
        const commandInstance = actionArgs.at(-1);
        const requestedFormat = commandInstance.optsWithGlobals?.().format ?? (0, global_format_1.getGlobalFormat)(commandInstance);
        const format = (0, output_1.resolveOutputFormat)(requestedFormat);
        if (format === null) {
            throw (0, errors_1.createUnsupportedOutputFormatError)({
                received: requestedFormat,
                commandBoundary: "version pin command output format"
            });
        }
        if (!(0, selection_1.isExactStableVersion)(version)) {
            throw (0, errors_1.createUsageError)("Version pin requires an exact stable version.", [
                `Received selector: ${version}`,
                "Use major.minor.patch form, for example 0.1.0.",
                "Aliases, partial selectors, and latest-installed are not accepted for repository pins."
            ]);
        }
        const result = writeRepositoryVersionPin({
            cwd: process.cwd(),
            version
        });
        (0, output_1.emitSuccess)({
            command: "version pin",
            format,
            text: renderVersionPinResult(result),
            data: result
        });
        getRootCommand(commandInstance ?? command).runtimeExitCode = errors_1.RuntimeExitCode.SUCCESS;
    });
    return command;
}
function createUseCommand(Command) {
    const command = new Command("use");
    command
        .description("Set the global default Day Shift version.")
        .argument("<version>")
        .action((version, ...actionArgs) => {
        if (!(0, selection_1.isExactStableVersion)(version)) {
            throw (0, errors_1.createUsageError)("Version use requires an exact stable version.", [
                `Received selector: ${version}`,
                "Use day-shift version alias set default <selector> for alias or partial selector targets."
            ]);
        }
        emitAliasWriteCommand({
            commandInstance: actionArgs.at(-1) ?? command,
            commandName: "version use",
            aliasName: "default",
            selector: version
        });
    });
    return command;
}
function writeRepositoryVersionPin(options) {
    const workspaceRoot = findVersionPinWorkspaceRoot(options.cwd);
    const pinPath = node_path_1.default.join(workspaceRoot, ".day-shift-version");
    const previousSelector = node_fs_1.default.existsSync(pinPath) && node_fs_1.default.statSync(pinPath).isFile()
        ? node_fs_1.default.readFileSync(pinPath, "utf8").trim()
        : null;
    node_fs_1.default.writeFileSync(pinPath, `${options.version}\n`);
    return {
        version: options.version,
        workspaceRoot,
        pinPath,
        previousSelector,
        selector: options.version,
        changed: previousSelector !== options.version,
        written: true
    };
}
function findVersionPinWorkspaceRoot(cwd) {
    let currentDirectory = node_path_1.default.resolve(cwd);
    while (true) {
        if (node_fs_1.default.existsSync(node_path_1.default.join(currentDirectory, ".day-shift", "config.toml")) ||
            node_fs_1.default.existsSync(node_path_1.default.join(currentDirectory, ".git"))) {
            return currentDirectory;
        }
        const parentDirectory = node_path_1.default.dirname(currentDirectory);
        if (parentDirectory === currentDirectory) {
            return node_path_1.default.resolve(cwd);
        }
        currentDirectory = parentDirectory;
    }
}
function writeVersionAlias(options) {
    validateAliasName(options.aliasName);
    validateAliasSelector(options.selector);
    const versionManagerRoot = (0, selection_1.resolveManagedVersionSelection)({ env: options.env }).versionManagerRoot;
    const aliasesDirectory = node_path_1.default.join(versionManagerRoot, "aliases");
    const aliasPath = node_path_1.default.join(aliasesDirectory, options.aliasName);
    const previousSelector = node_fs_1.default.existsSync(aliasPath) && node_fs_1.default.statSync(aliasPath).isFile()
        ? node_fs_1.default.readFileSync(aliasPath, "utf8").trim()
        : null;
    node_fs_1.default.mkdirSync(aliasesDirectory, { recursive: true });
    node_fs_1.default.writeFileSync(aliasPath, `${options.selector}\n`);
    return {
        aliasName: options.aliasName,
        selector: options.selector,
        aliasPath,
        previousSelector,
        changed: previousSelector !== options.selector,
        written: true
    };
}
function listVersionAliases(env) {
    const versionManagerRoot = (0, selection_1.resolveManagedVersionSelection)({ env }).versionManagerRoot;
    const aliasesDirectory = node_path_1.default.join(versionManagerRoot, "aliases");
    const aliases = node_fs_1.default.existsSync(aliasesDirectory)
        ? node_fs_1.default.readdirSync(aliasesDirectory, { withFileTypes: true })
            .filter((entry) => entry.isFile())
            .filter((entry) => /^[a-z][a-z0-9-]*$/.test(entry.name))
            .map((entry) => {
            const aliasPath = node_path_1.default.join(aliasesDirectory, entry.name);
            return {
                name: entry.name,
                selector: node_fs_1.default.readFileSync(aliasPath, "utf8").trim(),
                path: aliasPath
            };
        })
            .sort((left, right) => left.name.localeCompare(right.name))
        : [];
    return {
        versionManagerRoot,
        aliasesDirectory,
        aliases
    };
}
function validateAliasName(aliasName) {
    if (!/^[a-z][a-z0-9-]*$/.test(aliasName)) {
        throw (0, errors_1.createUsageError)("Version alias name is invalid.", [
            `Received alias: ${aliasName}`,
            "Use a lowercase alias name with letters, digits, and hyphens."
        ]);
    }
}
function validateAliasSelector(selector) {
    if (selector.trim() === "" || /[\\/]/.test(selector)) {
        throw (0, errors_1.createUsageError)("Version alias selector is invalid.", [
            "Alias selectors must be non-empty local selectors without path separators."
        ]);
    }
}
function emitAliasWriteCommand(options) {
    const requestedFormat = options.commandInstance.optsWithGlobals?.().format ?? (0, global_format_1.getGlobalFormat)(options.commandInstance);
    const format = (0, output_1.resolveOutputFormat)(requestedFormat);
    if (format === null) {
        throw (0, errors_1.createUnsupportedOutputFormatError)({
            received: requestedFormat,
            commandBoundary: `${options.commandName} command output format`
        });
    }
    const result = writeVersionAlias({
        env: process.env,
        aliasName: options.aliasName,
        selector: options.selector
    });
    (0, output_1.emitSuccess)({
        command: options.commandName,
        format,
        text: renderVersionAliasWriteResult(options.commandName, result),
        data: result
    });
    getRootCommand(options.commandInstance).runtimeExitCode = errors_1.RuntimeExitCode.SUCCESS;
}
function renderVersionPinResult(result) {
    return [
        (0, output_1.renderTerminalSection)({
            heading: "Day Shift version pin",
            headingStyle: "title",
            fields: [
                { label: "Version", value: result.version },
                { label: "Workspace root", value: result.workspaceRoot },
                { label: "Pin path", value: result.pinPath },
                { label: "Previous selector", value: result.previousSelector ?? "(none)" },
                { label: "Changed", value: result.changed }
            ]
        }),
        (0, output_1.renderTerminalBoundary)({
            kind: "write-applied",
            target: result.pinPath,
            targetLabel: "Pin file",
            stateSurface: ".day-shift-version"
        })
    ].join("\n\n");
}
function renderVersionAliasWriteResult(commandName, result) {
    return [
        (0, output_1.renderTerminalSection)({
            heading: commandName,
            headingStyle: "title",
            fields: [
                { label: "Alias", value: result.aliasName },
                { label: "Selector", value: result.selector },
                { label: "Alias path", value: result.aliasPath },
                { label: "Previous selector", value: result.previousSelector ?? "(none)" },
                { label: "Changed", value: result.changed }
            ]
        }),
        (0, output_1.renderTerminalBoundary)({
            kind: "write-applied",
            target: result.aliasPath,
            targetLabel: "Alias file",
            stateSurface: "version-manager aliases"
        })
    ].join("\n\n");
}
function renderVersionAliasListResult(result) {
    return [
        (0, output_1.renderTerminalSection)({
            heading: "Version aliases",
            headingStyle: "title",
            fields: [
                { label: "Version manager root", value: result.versionManagerRoot },
                { label: "Aliases directory", value: result.aliasesDirectory },
                { label: "Alias count", value: result.aliases.length }
            ]
        }),
        (0, output_1.renderTerminalCompactList)({
            heading: "Aliases",
            headingStyle: "section",
            entries: result.aliases.map((entry) => ({
                label: entry.name,
                fields: [
                    { label: "Selector", value: entry.selector },
                    { label: "Path", value: entry.path }
                ]
            })),
            emptyMessage: "(none)"
        })
    ].join("\n\n");
}
function renderVersionCurrentResult(result) {
    const summary = result.ok
        ? (0, output_1.renderTerminalSection)({
            heading: "Day Shift version current",
            headingStyle: "title",
            fields: [
                { label: "Selected version", value: result.version },
                { label: "Selection source", value: result.source },
                { label: "Selector", value: result.selector },
                { label: "Version manager root", value: result.versionManagerRoot },
                { label: "Package", value: result.packageDirectory },
                { label: "Metadata", value: result.metadataPath },
                { label: "Read only", value: result.readOnly },
                { label: "Network attempted", value: result.networkAttempted }
            ]
        })
        : (0, output_1.renderTerminalSection)({
            heading: "Day Shift version current",
            headingStyle: "title",
            fields: [
                { label: "State", value: "not selected" },
                { label: "Reason", value: result.reason },
                { label: "Version manager root", value: result.versionManagerRoot },
                { label: "Source", value: result.source ?? "(none)" },
                { label: "Selector", value: result.selector ?? "(none)" },
                { label: "Read only", value: result.readOnly },
                { label: "Network attempted", value: result.networkAttempted }
            ],
            lines: [result.message, ...result.details]
        });
    const installedVersions = (0, output_1.renderTerminalCompactList)({
        heading: "Installed versions",
        headingStyle: "section",
        entries: result.installedVersions.map((entry) => ({
            label: entry.version,
            fields: [
                { label: "Version directory", value: entry.versionDirectory },
                { label: "Package", value: entry.packageDirectory }
            ]
        })),
        emptyMessage: "(none)"
    });
    const diagnostics = (0, output_1.renderTerminalCompactList)({
        heading: "Selection diagnostics",
        headingStyle: "section",
        entries: result.diagnostics.map((diagnostic) => ({
            label: diagnostic.label,
            fields: [
                { label: "Source", value: diagnostic.source },
                { label: "Kind", value: diagnostic.kind },
                { label: "Selector", value: diagnostic.selector ?? "(none)" },
                { label: "Path", value: diagnostic.path ?? "(none)" }
            ],
            lines: [diagnostic.message]
        })),
        emptyMessage: "(none)"
    });
    return result.ok
        ? [summary, installedVersions, diagnostics].join("\n\n")
        : [
            summary,
            installedVersions,
            diagnostics,
            (0, output_1.renderTerminalBoundary)({ kind: "no-write-failure", reason: result.reason })
        ].join("\n\n");
}
function createCheckCommand(Command) {
    const command = new Command("check");
    command
        .description("Check Day Shift version availability only after explicit network approval.")
        .argument("[version]")
        .option("--network", "Approve the declared network availability check.")
        .action(async (version, ...actionArgs) => {
        const commandInstance = actionArgs.at(-1);
        const requestedFormat = commandInstance.optsWithGlobals?.().format ?? (0, global_format_1.getGlobalFormat)(commandInstance);
        const format = (0, output_1.resolveOutputFormat)(requestedFormat);
        if (format === null) {
            throw (0, errors_1.createUnsupportedOutputFormatError)({
                received: requestedFormat,
                commandBoundary: "version check command output format"
            });
        }
        const options = commandInstance.opts();
        if (!options.network) {
            emitVersionContract(commandInstance ?? command, (0, command_contract_1.createNetworkApprovalRequiredContract)());
            return;
        }
        const result = await checkVersionAvailability({
            requestedVersion: typeof version === "string" && version.trim() !== "" ? version.trim() : null,
            env: process.env
        });
        (0, output_1.emitSuccess)({
            command: "version check",
            format,
            text: renderVersionCheckResult(result),
            data: result
        });
        getRootCommand(commandInstance ?? command).runtimeExitCode = errors_1.RuntimeExitCode.SUCCESS;
    });
    return command;
}
async function checkVersionAvailability(options) {
    const versionManagerRoot = (0, state_layout_1.resolveVersionManagerRoot)({ env: options.env });
    const installedVersions = (0, selection_1.listInstalledVersions)(versionManagerRoot);
    const metadataUrl = resolveVersionCheckMetadataUrl(options.env);
    const fixturePath = options.env.DAY_SHIFT_VERSION_CHECK_FIXTURE?.trim();
    if (fixturePath !== undefined && fixturePath !== "") {
        try {
            const parsed = parseReleaseManifestIndex(JSON.parse(node_fs_1.default.readFileSync(fixturePath, "utf8")));
            if (!parsed.ok) {
                return {
                    state: "metadata-malformed",
                    requestedVersion: options.requestedVersion,
                    available: null,
                    latestVersion: null,
                    metadataUrl: fixturePath,
                    metadataSource: "local-test-fixture",
                    installedVersions,
                    networkAttempted: true,
                    noWrite: true,
                    details: parsed.details,
                    recovery: [
                        "Retry later after the Day Shift downloads manifest is corrected.",
                        "Continue using local installed-version state for offline workflows."
                    ]
                };
            }
            return createVersionCheckResultFromManifest({
                requestedVersion: options.requestedVersion,
                metadataUrl: fixturePath,
                metadataSource: "local-test-fixture",
                installedVersions,
                manifest: parsed
            });
        }
        catch (error) {
            return metadataUnavailable({
                requestedVersion: options.requestedVersion,
                metadataUrl: fixturePath,
                metadataSource: "local-test-fixture",
                installedVersions,
                detail: error instanceof Error ? error.message : String(error)
            });
        }
    }
    if (!metadataUrl.ok) {
        return {
            state: "unsupported-metadata-source",
            requestedVersion: options.requestedVersion,
            available: null,
            latestVersion: null,
            metadataUrl: metadataUrl.url,
            metadataSource: null,
            installedVersions,
            networkAttempted: false,
            noWrite: true,
            details: metadataUrl.details,
            recovery: [
                "Use the default Day Shift-owned downloads manifest or a local test fixture endpoint.",
                "Continue using local installed-version state for offline workflows."
            ]
        };
    }
    try {
        const response = await fetch(metadataUrl.url, {
            headers: { accept: "application/json" }
        });
        if (!response.ok) {
            return metadataUnavailable({
                requestedVersion: options.requestedVersion,
                metadataUrl: metadataUrl.url,
                metadataSource: metadataUrl.source,
                installedVersions,
                detail: `HTTP ${response.status} ${response.statusText}`.trim()
            });
        }
        const parsed = parseReleaseManifestIndex(await response.json());
        if (!parsed.ok) {
            return {
                state: "metadata-malformed",
                requestedVersion: options.requestedVersion,
                available: null,
                latestVersion: null,
                metadataUrl: metadataUrl.url,
                metadataSource: metadataUrl.source,
                installedVersions,
                networkAttempted: true,
                noWrite: true,
                details: parsed.details,
                recovery: [
                    "Retry later after the Day Shift downloads manifest is corrected.",
                    "Continue using local installed-version state for offline workflows."
                ]
            };
        }
        return createVersionCheckResultFromManifest({
            requestedVersion: options.requestedVersion,
            metadataUrl: metadataUrl.url,
            metadataSource: metadataUrl.source,
            installedVersions,
            manifest: parsed
        });
    }
    catch (error) {
        return metadataUnavailable({
            requestedVersion: options.requestedVersion,
            metadataUrl: metadataUrl.url,
            metadataSource: metadataUrl.source,
            installedVersions,
            detail: error instanceof Error ? error.message : String(error)
        });
    }
}
function createVersionCheckResultFromManifest(options) {
    const available = options.requestedVersion === null
        ? true
        : options.manifest.versions.some((entry) => entry.version === options.requestedVersion && entry.available);
    return {
        state: available ? "available" : "unavailable",
        requestedVersion: options.requestedVersion,
        available,
        latestVersion: options.manifest.latestVersion,
        metadataUrl: options.metadataUrl,
        metadataSource: options.metadataSource,
        installedVersions: options.installedVersions,
        networkAttempted: true,
        noWrite: true,
        details: [
            `Manifest versions: ${options.manifest.versions.map((entry) => entry.version).join(", ") || "(none)"}`,
            options.requestedVersion === null
                ? "No exact requested version was supplied; latest metadata was reported only."
                : `Requested version ${options.requestedVersion} is ${available ? "available" : "not available"} in Day Shift metadata.`
        ],
        recovery: [
            "Use local installed-version state for install, uninstall, selection, shim dispatch, and license workflows.",
            "Set aliases explicitly with day-shift version alias commands if a local selector should change."
        ]
    };
}
function renderVersionCheckResult(result) {
    return [
        (0, output_1.renderTerminalSection)({
            heading: "Day Shift version check",
            headingStyle: "title",
            fields: [
                { label: "State", value: result.state },
                { label: "Requested version", value: result.requestedVersion ?? "(none)" },
                { label: "Available", value: result.available === null ? "(unknown)" : result.available },
                { label: "Latest version", value: result.latestVersion ?? "(unknown)" },
                { label: "Metadata URL", value: result.metadataUrl ?? "(none)" },
                { label: "Metadata source", value: result.metadataSource ?? "(none)" },
                { label: "Network attempted", value: result.networkAttempted },
                { label: "No write", value: result.noWrite }
            ]
        }),
        (0, output_1.renderTerminalCompactList)({
            heading: "Installed versions",
            headingStyle: "section",
            entries: result.installedVersions.map((entry) => ({
                label: entry.version,
                fields: [
                    { label: "Version directory", value: entry.versionDirectory },
                    { label: "Package", value: entry.packageDirectory }
                ]
            })),
            emptyMessage: "(none)"
        }),
        (0, output_1.renderTerminalCompactList)({
            heading: "Details",
            headingStyle: "section",
            entries: result.details.map((line) => ({ label: line }))
        }),
        (0, output_1.renderTerminalCompactList)({
            heading: "Recovery",
            headingStyle: "section",
            entries: result.recovery.map((line) => ({ label: line }))
        }),
        (0, output_1.renderTerminalBoundary)({ kind: "read-only" })
    ].join("\n\n");
}
function metadataUnavailable(options) {
    return {
        state: "metadata-unavailable",
        requestedVersion: options.requestedVersion,
        available: null,
        latestVersion: null,
        metadataUrl: options.metadataUrl,
        metadataSource: options.metadataSource,
        installedVersions: options.installedVersions,
        networkAttempted: true,
        noWrite: true,
        details: [options.detail],
        recovery: [
            "Retry the approved Day Shift-owned metadata check later.",
            "Continue using local installed-version state for offline workflows."
        ]
    };
}
function resolveVersionCheckMetadataUrl(env) {
    const configured = env.DAY_SHIFT_VERSION_CHECK_URL?.trim();
    const rawUrl = configured && configured !== ""
        ? configured
        : "https://day-shift.dev/downloads/release-manifest.json";
    let parsed;
    try {
        parsed = new URL(rawUrl);
    }
    catch {
        return {
            ok: false,
            url: rawUrl,
            details: [`Version check metadata URL is malformed: ${rawUrl}`]
        };
    }
    const isDayShiftWebsite = parsed.protocol === "https:" &&
        (parsed.hostname === "day-shift.dev" || parsed.hostname === "www.day-shift.dev") &&
        parsed.pathname.startsWith("/downloads/");
    const isLocalFixture = configured !== undefined &&
        parsed.protocol === "http:" &&
        (parsed.hostname === "127.0.0.1" || parsed.hostname === "localhost");
    if (isDayShiftWebsite) {
        return { ok: true, url: parsed.toString(), source: "day-shift-website" };
    }
    if (isLocalFixture) {
        return { ok: true, url: parsed.toString(), source: "local-test-fixture" };
    }
    return {
        ok: false,
        url: parsed.toString(),
        details: [
            "Version check metadata must come from the Day Shift-owned downloads manifest.",
            "GitHub, npm, public registry, and arbitrary provider URLs are not supported."
        ]
    };
}
function parseReleaseManifestIndex(input) {
    if (typeof input !== "object" || input === null) {
        return { ok: false, details: ["Release manifest index must be a JSON object."] };
    }
    const document = input;
    if (!Array.isArray(document.versions)) {
        return { ok: false, details: ["Release manifest index must include versions[]."] };
    }
    const versions = [];
    for (const entry of document.versions) {
        if (typeof entry !== "object" || entry === null) {
            return { ok: false, details: ["Release manifest version entries must be objects."] };
        }
        const version = entry.version;
        const status = entry.status;
        if (typeof version !== "string" || !(0, selection_1.isExactStableVersion)(version)) {
            return { ok: false, details: ["Release manifest version entries must include exact stable versions."] };
        }
        versions.push({
            version,
            available: status === undefined || status === "active" || status === "deprecated"
        });
    }
    const latestVersion = typeof document.latest?.version === "string" && (0, selection_1.isExactStableVersion)(document.latest.version)
        ? document.latest.version
        : versions.at(-1)?.version ?? null;
    return { ok: true, latestVersion, versions };
}
function createDoctorCommand(Command) {
    const command = new Command("doctor");
    command
        .description("Inspect local version-manager runtime context.")
        .action((...actionArgs) => {
        const commandInstance = actionArgs.at(-1);
        const requestedFormat = commandInstance.optsWithGlobals?.().format ?? (0, global_format_1.getGlobalFormat)(commandInstance);
        const format = (0, output_1.resolveOutputFormat)(requestedFormat);
        if (format === null) {
            throw (0, errors_1.createUnsupportedOutputFormatError)({
                received: requestedFormat,
                commandBoundary: "version doctor command output format"
            });
        }
        const report = (0, doctor_1.createVersionDoctorReport)(process.env);
        (0, output_1.emitSuccess)({
            command: "version doctor",
            format,
            text: (0, doctor_1.renderVersionDoctorReport)(report, format),
            data: report
        });
        getRootCommand(commandInstance ?? command).runtimeExitCode = errors_1.RuntimeExitCode.SUCCESS;
    });
    return command;
}
function createAliasCommand(Command) {
    const command = new Command("alias");
    command
        .description("Inspect or mutate local version aliases.")
        .addHelpText("after", [
        "",
        "Alias operations:",
        "  list",
        "  set <name> <version>"
    ].join("\n"));
    const listCommand = new Command("list");
    listCommand
        .description("List local version aliases.")
        .action((...actionArgs) => {
        const commandInstance = actionArgs.at(-1);
        const requestedFormat = commandInstance.optsWithGlobals?.().format ?? (0, global_format_1.getGlobalFormat)(commandInstance);
        const format = (0, output_1.resolveOutputFormat)(requestedFormat);
        if (format === null) {
            throw (0, errors_1.createUnsupportedOutputFormatError)({
                received: requestedFormat,
                commandBoundary: "version alias list command output format"
            });
        }
        const result = listVersionAliases(process.env);
        (0, output_1.emitSuccess)({
            command: "version alias list",
            format,
            text: renderVersionAliasListResult(result),
            data: result
        });
        getRootCommand(commandInstance ?? command).runtimeExitCode = errors_1.RuntimeExitCode.SUCCESS;
    });
    (0, registration_1.registerCommand)(command, listCommand);
    const setCommand = new Command("set");
    setCommand
        .description("Set a local version alias.")
        .argument("<name>")
        .argument("<version>")
        .action((name, version, ...actionArgs) => {
        emitAliasWriteCommand({
            commandInstance: actionArgs.at(-1) ?? command,
            commandName: "version alias set",
            aliasName: name,
            selector: version
        });
    });
    (0, registration_1.registerCommand)(command, setCommand);
    command.action((...actionArgs) => {
        const commandInstance = actionArgs.at(-1);
        emitVersionContract(commandInstance ?? command, (0, command_contract_1.createDeferredVersionCommandContract)({
            command: "version alias",
            operation: "alias"
        }));
    });
    return command;
}
function emitVersionContract(commandInstance, contract) {
    const requestedFormat = commandInstance.optsWithGlobals?.().format ?? (0, global_format_1.getGlobalFormat)(commandInstance);
    const format = (0, output_1.resolveOutputFormat)(requestedFormat);
    if (format === null) {
        throw (0, errors_1.createUnsupportedOutputFormatError)({
            received: requestedFormat,
            commandBoundary: `${contract.command} command output format`
        });
    }
    (0, output_1.emitSuccess)({
        command: contract.command,
        format,
        text: (0, command_contract_1.renderVersionCommandContract)(contract, format),
        data: (0, command_contract_1.toVersionCommandContractData)(contract)
    });
    getRootCommand(commandInstance).runtimeExitCode = contract.exitCode;
}
function getRootCommand(commandInstance) {
    let current = commandInstance;
    while (current.parent !== undefined && current.parent !== null) {
        current = current.parent;
    }
    return current;
}
