"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.uninstallManagedVersion = uninstallManagedVersion;
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const toml = __importStar(require("@iarna/toml"));
const state_layout_1 = require("./state-layout");
const selection_1 = require("./selection");
function uninstallManagedVersion(options = {}) {
    const versionManagerRoot = (0, state_layout_1.resolveVersionManagerRoot)(options);
    const installedVersions = (0, selection_1.listInstalledVersions)(versionManagerRoot);
    const target = options.target?.trim() ?? "";
    const cwd = node_path_1.default.resolve(options.cwd ?? process.cwd());
    const replacementVersion = options.replacementVersion?.trim() ?? null;
    const confirmSelectedRemoval = options.confirmSelectedRemoval === true;
    if (target === "") {
        return {
            ok: false,
            reason: "missing-target",
            message: "Version uninstall requires an explicit target version.",
            details: [
                "Use major.minor.patch form, for example: day-shift version uninstall 0.1.10.",
                "List installed versions before uninstalling: day-shift version list.",
                "No version-manager state was mutated."
            ],
            versionManagerRoot,
            target: null,
            installedVersions,
            affectedSelectors: []
        };
    }
    if (!(0, selection_1.isExactStableVersion)(target)) {
        return {
            ok: false,
            reason: "invalid-target",
            message: "Version uninstall requires an exact stable version target.",
            details: [
                `Received selector: ${target}`,
                "Aliases, partial versions, latest-installed, prerelease versions, build metadata, and paths are not accepted for uninstall.",
                "Use major.minor.patch form, for example: day-shift version uninstall 0.1.10.",
                "No version-manager state was mutated."
            ],
            versionManagerRoot,
            target,
            installedVersions,
            affectedSelectors: []
        };
    }
    const installedVersion = installedVersions.find((entry) => entry.version === target);
    if (installedVersion === undefined) {
        return {
            ok: false,
            reason: "target-not-installed",
            message: "Target Day Shift version is not installed.",
            details: [
                `Requested target: ${target}`,
                `Installed versions: ${installedVersions.length === 0
                    ? "(none)"
                    : installedVersions.map((entry) => entry.version).join(", ")}`,
                "List installed versions before uninstalling: day-shift version list.",
                "No version-manager state was mutated."
            ],
            versionManagerRoot,
            target,
            installedVersions,
            affectedSelectors: []
        };
    }
    const affectedSelectors = findAffectedUninstallSelectors({
        versionManagerRoot,
        cwd,
        target
    });
    if (replacementVersion !== null && confirmSelectedRemoval) {
        return {
            ok: false,
            reason: "invalid-replacement",
            message: "Version uninstall replacement cannot be combined with selected-removal confirmation.",
            details: [
                "Use either --replace-with <version> or --confirm-selected-removal.",
                "No version-manager state was mutated."
            ],
            versionManagerRoot,
            target,
            installedVersions,
            affectedSelectors
        };
    }
    if (replacementVersion !== null) {
        const replacementFailure = validateReplacementVersion({
            replacementVersion,
            target,
            installedVersions
        });
        if (replacementFailure !== null) {
            return {
                ok: false,
                reason: "invalid-replacement",
                message: "Version uninstall replacement is invalid.",
                details: [
                    replacementFailure,
                    "Replacement must be another exact installed version.",
                    "No version-manager state was mutated."
                ],
                versionManagerRoot,
                target,
                installedVersions,
                affectedSelectors
            };
        }
    }
    if (affectedSelectors.length > 0 && replacementVersion === null && !confirmSelectedRemoval) {
        return {
            ok: false,
            reason: "affected-selectors-require-decision",
            message: "Target Day Shift version is selected by one or more selectors.",
            details: [
                `Requested target: ${target}`,
                ...affectedSelectors.map((selector) => `${selector.label}: ${selector.path}`),
                "Use --replace-with <version> to update affected selectors before uninstalling.",
                "Use --confirm-selected-removal to remove the target while leaving affected selectors unchanged.",
                "No version-manager state was mutated."
            ],
            versionManagerRoot,
            target,
            installedVersions,
            affectedSelectors
        };
    }
    if (replacementVersion !== null) {
        applySelectorReplacement({
            affectedSelectors,
            replacementVersion
        });
    }
    return removeManagedVersionTarget({
        versionManagerRoot,
        target,
        installedVersion,
        affectedSelectors,
        replacementVersion,
        confirmedSelectedRemoval: confirmSelectedRemoval
    });
}
function removeManagedVersionTarget(options) {
    const receiptsDirectory = node_path_1.default.join(options.versionManagerRoot, "installs", "receipts");
    const removedReceiptPaths = [];
    const preservedReceiptPaths = [];
    node_fs_1.default.rmSync(options.installedVersion.versionDirectory, { recursive: true, force: true });
    if (node_fs_1.default.existsSync(receiptsDirectory) && node_fs_1.default.statSync(receiptsDirectory).isDirectory()) {
        for (const entry of node_fs_1.default.readdirSync(receiptsDirectory, { withFileTypes: true })) {
            if (!entry.isFile()) {
                continue;
            }
            const receiptPath = node_path_1.default.join(receiptsDirectory, entry.name);
            if (receiptMatchesTarget(receiptPath, options.target)) {
                node_fs_1.default.rmSync(receiptPath, { force: true });
                removedReceiptPaths.push(receiptPath);
            }
            else {
                preservedReceiptPaths.push(receiptPath);
            }
        }
    }
    return {
        ok: true,
        versionManagerRoot: options.versionManagerRoot,
        target: options.target,
        versionDirectory: options.installedVersion.versionDirectory,
        removedVersionDirectory: true,
        receiptsDirectory,
        removedReceiptPaths: removedReceiptPaths.sort(),
        preservedReceiptPaths: preservedReceiptPaths.sort(),
        affectedSelectors: options.affectedSelectors,
        replacementVersion: options.replacementVersion,
        replacementApplied: options.replacementVersion !== null,
        confirmedSelectedRemoval: options.confirmedSelectedRemoval,
        preservedState: [
            "sibling managed versions",
            options.replacementVersion === null ? "version-manager aliases" : "unaffected version-manager aliases",
            options.replacementVersion === null ? "repository pins" : "unaffected repository selectors",
            "signed license files",
            "recovered purchase files",
            "non-target receipts",
            "cache and logs"
        ],
        written: true
    };
}
function receiptMatchesTarget(receiptPath, target) {
    try {
        const parsed = JSON.parse(node_fs_1.default.readFileSync(receiptPath, "utf8"));
        return parsed.version === target;
    }
    catch {
        return false;
    }
}
function findAffectedUninstallSelectors(options) {
    return [
        ...findAffectedAliases(options),
        ...findAffectedRepositorySelectors(options)
    ].sort((left, right) => left.path.localeCompare(right.path) || left.label.localeCompare(right.label));
}
function findAffectedAliases(options) {
    const aliasesDirectory = node_path_1.default.join(options.versionManagerRoot, "aliases");
    if (!node_fs_1.default.existsSync(aliasesDirectory) || !node_fs_1.default.statSync(aliasesDirectory).isDirectory()) {
        return [];
    }
    return 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,
            path: aliasPath,
            selector: node_fs_1.default.readFileSync(aliasPath, "utf8").trim()
        };
    })
        .filter((entry) => entry.selector === options.target)
        .map((entry) => ({
        kind: "global-alias",
        label: `${entry.name} alias`,
        selector: entry.selector,
        path: entry.path
    }));
}
function findAffectedRepositorySelectors(options) {
    const workspaceRoot = findNearestDayShiftWorkspace(options.cwd);
    const selectors = [];
    const pinPath = findNearestRepositoryPinPath(options.cwd);
    if (pinPath !== null) {
        const selector = node_fs_1.default.readFileSync(pinPath, "utf8").trim();
        if (selector === options.target) {
            selectors.push({
                kind: "repository-pin",
                label: "nearest .day-shift-version",
                selector,
                path: pinPath
            });
        }
    }
    if (workspaceRoot === null) {
        return selectors;
    }
    for (const config of [
        {
            kind: "repository-local-config",
            label: ".day-shift/local.toml",
            path: node_path_1.default.join(workspaceRoot, ".day-shift", "local.toml")
        },
        {
            kind: "repository-config",
            label: ".day-shift/config.toml",
            path: node_path_1.default.join(workspaceRoot, ".day-shift", "config.toml")
        }
    ]) {
        const selector = readTomlVersionSelector(config.path);
        if (selector === options.target) {
            selectors.push({
                kind: config.kind,
                label: config.label,
                selector,
                path: config.path
            });
        }
    }
    return selectors;
}
function validateReplacementVersion(options) {
    if (!(0, selection_1.isExactStableVersion)(options.replacementVersion)) {
        return `Received replacement selector: ${options.replacementVersion}`;
    }
    if (options.replacementVersion === options.target) {
        return "Replacement version must be different from the uninstall target.";
    }
    if (!options.installedVersions.some((entry) => entry.version === options.replacementVersion)) {
        return `Replacement version is not installed: ${options.replacementVersion}`;
    }
    return null;
}
function applySelectorReplacement(options) {
    for (const selector of options.affectedSelectors) {
        if (selector.kind === "repository-local-config" || selector.kind === "repository-config") {
            replaceTomlVersionSelector(selector.path, options.replacementVersion);
        }
        else {
            node_fs_1.default.writeFileSync(selector.path, `${options.replacementVersion}\n`);
        }
    }
}
function findNearestRepositoryPinPath(cwd) {
    let currentDirectory = node_path_1.default.resolve(cwd);
    while (true) {
        const candidatePath = node_path_1.default.join(currentDirectory, ".day-shift-version");
        if (node_fs_1.default.existsSync(candidatePath) && node_fs_1.default.statSync(candidatePath).isFile()) {
            return candidatePath;
        }
        const parentDirectory = node_path_1.default.dirname(currentDirectory);
        if (parentDirectory === currentDirectory) {
            return null;
        }
        currentDirectory = parentDirectory;
    }
}
function findNearestDayShiftWorkspace(cwd) {
    let currentDirectory = node_path_1.default.resolve(cwd);
    while (true) {
        const dayShiftDirectory = node_path_1.default.join(currentDirectory, ".day-shift");
        if (node_fs_1.default.existsSync(node_path_1.default.join(dayShiftDirectory, "local.toml")) ||
            node_fs_1.default.existsSync(node_path_1.default.join(dayShiftDirectory, "config.toml"))) {
            return currentDirectory;
        }
        const parentDirectory = node_path_1.default.dirname(currentDirectory);
        if (parentDirectory === currentDirectory) {
            return null;
        }
        currentDirectory = parentDirectory;
    }
}
function readTomlVersionSelector(configPath) {
    if (!node_fs_1.default.existsSync(configPath) || !node_fs_1.default.statSync(configPath).isFile()) {
        return null;
    }
    const contents = node_fs_1.default.readFileSync(configPath, "utf8");
    if (contents.trim() === "") {
        return null;
    }
    const parsed = toml.parse(contents);
    return typeof parsed.version === "string" ? parsed.version.trim() : null;
}
function replaceTomlVersionSelector(configPath, replacementVersion) {
    const contents = node_fs_1.default.existsSync(configPath) ? node_fs_1.default.readFileSync(configPath, "utf8") : "";
    const nextContents = /^version\s*=/m.test(contents)
        ? contents.replace(/^version\s*=.*$/m, `version = "${replacementVersion}"`)
        : `${contents.trimEnd()}${contents.trim() === "" ? "" : "\n"}version = "${replacementVersion}"\n`;
    node_fs_1.default.writeFileSync(configPath, nextContents.endsWith("\n") ? nextContents : `${nextContents}\n`);
}
