"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseRetentionKeep = parseRetentionKeep;
exports.applyReleaseRetention = applyReleaseRetention;
exports.applyReleaseCleanup = applyReleaseCleanup;
exports.listReleaseDirectoryEntries = listReleaseDirectoryEntries;
exports.compareStableVersionsDescending = compareStableVersionsDescending;
// Mechanically extracted from output-lifecycle.ts to keep release responsibilities bounded.
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const errors_1 = require("../../../lib/errors");
const version_1 = require("./version");
const output_lifecycle_lifecycle_contracts_1 = require("./output-lifecycle-lifecycle-contracts");
const output_lifecycle_output_state_1 = require("./output-lifecycle-output-state");
function parseRetentionKeep(value) {
    const raw = typeof value === 'string' && value.trim().length > 0 ? value.trim() : '3';
    const keep = Number(raw);
    if (!Number.isInteger(keep) || keep < 0) {
        throw (0, errors_1.createUsageError)(`Invalid release retention keep count: ${raw}`, [
            'Reason: invalid-retention-keep-count',
            'Recovery: provide a non-negative integer, for example --keep 3.',
            'Exit behavior: exits before local generated release output is pruned.',
        ]);
    }
    return keep;
}
function applyReleaseRetention(options) {
    if (options.state.versionDirectoryRelative === null) {
        throw (0, errors_1.createUsageError)('Release retention requires a resolved current version directory.', [
            'Exit behavior: exits before local generated release output is pruned.',
        ]);
    }
    const entries = listReleaseDirectoryEntries(options.state);
    const successfulPriorEntries = entries
        .filter((entry) => entry.name !== options.currentVersion)
        .filter((entry) => entry.marker.valid && entry.marker.version === entry.name)
        .sort((left, right) => compareStableVersionsDescending(left.name, right.name));
    const retainedPriorPaths = new Set(successfulPriorEntries.slice(0, options.keepSuccessfulPriorCount).map((entry) => entry.relativePath));
    const retainedPaths = [options.state.versionDirectoryRelative, ...Array.from(retainedPriorPaths)];
    const removedEntries = entries.filter((entry) => {
        if (entry.name === options.currentVersion) {
            return false;
        }
        return !retainedPriorPaths.has(entry.relativePath);
    });
    if (!options.dryRun) {
        for (const entry of removedEntries) {
            node_fs_1.default.rmSync(entry.path, { recursive: true, force: true });
        }
    }
    return {
        kind: 'local-retention',
        dryRun: options.dryRun,
        changed: !options.dryRun && removedEntries.length > 0,
        removedPaths: removedEntries.map((entry) => entry.relativePath),
        retainedPaths,
        message: options.dryRun
            ? 'Dry run reported local generated release directories that retention would remove.'
            : 'Applied local generated release directory retention.',
    };
}
function applyReleaseCleanup(options) {
    if (!options.dryRun && !options.confirm) {
        throw (0, errors_1.createUsageError)('Release cleanup requires --confirm before deleting local generated release output.', [
            'Reason: cleanup-confirmation-required',
            'Recovery: rerun with --confirm, or use --dry-run to inspect the local-only cleanup target.',
            'Exit behavior: exits before local generated release output is deleted.',
        ]);
    }
    const exists = node_fs_1.default.existsSync(options.state.releaseRoot);
    if (!options.dryRun && exists) {
        node_fs_1.default.rmSync(options.state.releaseRoot, { recursive: true, force: true });
    }
    return {
        kind: 'local-cleanup',
        dryRun: options.dryRun,
        changed: !options.dryRun && exists,
        removedPaths: exists ? [options.state.releaseRootRelative] : [],
        retainedPaths: [],
        message: options.dryRun
            ? 'Dry run reported the local generated release output root that cleanup would remove.'
            : 'Removed local generated release output only; published immutable artifacts were not touched.',
    };
}
function listReleaseDirectoryEntries(state) {
    if (!node_fs_1.default.existsSync(state.releaseRoot)) {
        return [];
    }
    return node_fs_1.default
        .readdirSync(state.releaseRoot, { withFileTypes: true })
        .filter((entry) => entry.isDirectory())
        .map((entry) => {
        const entryPath = node_path_1.default.join(state.releaseRoot, entry.name);
        const markerPath = node_path_1.default.join(entryPath, output_lifecycle_lifecycle_contracts_1.RELEASE_SUCCESS_MARKER_FILE);
        return {
            name: entry.name,
            path: entryPath,
            relativePath: `${state.releaseRootRelative}/${entry.name}`,
            marker: (0, output_lifecycle_output_state_1.readReleaseSuccessMarker)({
                releaseRoot: state.releaseRoot,
                releaseRootRelative: state.releaseRootRelative,
                versionDirectory: entryPath,
                versionDirectoryRelative: `${state.releaseRootRelative}/${entry.name}`,
                stagingDirectory: node_path_1.default.join(entryPath, 'staging'),
                stagingDirectoryRelative: `${state.releaseRootRelative}/${entry.name}/staging`,
                successMarkerPath: markerPath,
                successMarkerPathRelative: `${state.releaseRootRelative}/${entry.name}/${output_lifecycle_lifecycle_contracts_1.RELEASE_SUCCESS_MARKER_FILE}`,
            }),
        };
    });
}
function compareStableVersionsDescending(left, right) {
    const parsedLeft = (0, version_1.parseReleaseVersion)(left);
    const parsedRight = (0, version_1.parseReleaseVersion)(right);
    if (!parsedLeft.ok && !parsedRight.ok) {
        return right.localeCompare(left);
    }
    if (!parsedLeft.ok) {
        return 1;
    }
    if (!parsedRight.ok) {
        return -1;
    }
    return (parsedRight.major - parsedLeft.major || parsedRight.minor - parsedLeft.minor || parsedRight.patch - parsedLeft.patch);
}
