"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
require("reflect-metadata");
const core_1 = require("@oclif/core");
const command_base_exec_1 = require("../../command-base-exec");
class SnapshotUntag extends command_base_exec_1.CommandBaseExec {
    constructor() {
        super(...arguments);
        this.infrxAliases = ["cluster:stack:untag"];
    }
    captureArgs() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { flags } = yield this.parse(SnapshotUntag);
            const partial = {};
            const explicit = {};
            if (flags.enterprise) {
                partial.enterprise = flags.enterprise.trim();
                explicit.enterprise = partial.enterprise;
            }
            if (flags.version) {
                partial.version = flags.version.trim();
                explicit.version = partial.version;
            }
            if (flags.tag) {
                partial.tagName = flags.tag.trim();
                explicit.tagName = partial.tagName;
            }
            return [partial, false, explicit];
        });
    }
    buildCandidate_silently(partial, _rootMap, _explicit) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (!partial.version)
                throw new Error("Snapshot version (--version / -v) is required in silent mode.");
            if (!partial.tagName)
                throw new Error("Tag name (--tag / -t) is required in silent mode.");
            const snapshot = yield this.snapshotFetchByVersion(partial.enterprise, partial.version);
            const tags = yield this.tagsFetchForSnapshot(snapshot);
            const tag = tags.find(t => t.name === partial.tagName);
            if (!tag)
                throw new Error(`Tag "${partial.tagName}" does not exist on snapshot "${partial.version}".`);
            return { enterprise: partial.enterprise, snapshot, tag };
        });
    }
    buildCandidate_interactively(partial, _rootMap, _takeDefaults, explicit) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const snapshot = yield this.snapshotPromptFor(partial.enterprise, partial.version, explicit === null || explicit === void 0 ? void 0 : explicit.version);
            if (!snapshot)
                return undefined;
            const tags = yield this.tagsFetchForSnapshot(snapshot);
            if (tags.length === 0) {
                this._ui.userMessage(`Snapshot ${this._styler.hilite(snapshot.version)} has no tags to remove.`);
                return undefined;
            }
            const tag = yield this.tagPromptFor(tags, partial.tagName, explicit === null || explicit === void 0 ? void 0 : explicit.tagName);
            if (!tag)
                return undefined;
            return { enterprise: partial.enterprise, snapshot, tag };
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("-e", candidate.enterprise);
        cmd.push("-v", candidate.snapshot.version);
        cmd.push("-t", candidate.tag.name);
        cmd.push("--silent");
        return cmd;
    }
    executeTask(candidate) {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            this._ui.startSpinner(`Removing tag "${candidate.tag.name}" from snapshot ${candidate.snapshot.version}...`);
            const result = yield this._codiacApi.Tag.tryDeleteWhere({ ids: [candidate.tag.id] });
            this._ui.stopSpinner(result.success ? "done" : "failed");
            if (result.success) {
                this._ui.userMessage(`${this._styler.colorGood("SUCCESS")}: Tag ${this._styler.hilite(candidate.tag.name)} removed from snapshot ${this._styler.hilite(candidate.snapshot.version)}.`);
            }
            else {
                this._ui.userMessage(`${this._styler.colorCritical("ERROR")}: ${result.message}`);
                throw (_a = result.error) !== null && _a !== void 0 ? _a : new Error((_b = result.message) !== null && _b !== void 0 ? _b : "Failed to remove tag.");
            }
        });
    }
    snapshotFetchByVersion(enterprise, version) {
        var _a;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const result = yield this._codiacApi.EnterpriseVersionConfig.tryReadMany({
                enterprise,
                version,
            });
            if (result.error)
                throw result.error;
            const snapshot = (_a = result.output) === null || _a === void 0 ? void 0 : _a[0];
            if (!snapshot)
                throw new Error(`Snapshot version "${version}" not found in enterprise "${enterprise}".`);
            return snapshot;
        });
    }
    tagsFetchForSnapshot(snapshot) {
        var _a;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const result = yield this._codiacApi.Tag.tryReadMany({
                ownerType: "EnterpriseVersionConfig",
                ownerId: { $in: [snapshot.id] },
            }, { throwNotFound: false });
            if (result.error)
                throw result.error;
            return (_a = result.output) !== null && _a !== void 0 ? _a : [];
        });
    }
    snapshotPromptFor(enterprise, versionHint, explicitVersion) {
        var _a;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            this._ui.startSpinner("Retrieving snapshots");
            const result = yield this._codiacApi.EnterpriseVersionConfig.tryReadMany({
                enterprise,
                take: 100,
                sort: "created~desc",
            });
            if (result.error) {
                this._ui.stopSpinner("failed");
                throw result.error;
            }
            const snapshots = (_a = result.output) !== null && _a !== void 0 ? _a : [];
            this._ui.stopSpinner(`found ${snapshots.length}`);
            if (snapshots.length === 0) {
                this._ui.userMessage("No snapshots found in enterprise: " + enterprise);
                return undefined;
            }
            let matched = versionHint
                ? snapshots.find(s => s.version.toLowerCase() === versionHint.toLowerCase())
                : undefined;
            if (matched && explicitVersion) {
                this._ui.userMessage(`Continuing with snapshot ${this._styler.hilite(matched.version)}`);
                return matched;
            }
            if (versionHint && !matched) {
                this._ui.userMessage(this._styler.colorWarning(`Snapshot "${versionHint}" not found; please select from the list.`));
            }
            const choices = snapshots.map(s => ({
                name: this.snapshotFormatChoice(s),
                value: s.version,
            }));
            const selected = yield this._ui.promptSelectFuzzy("snapshotVersion", "Select a snapshot:", () => tslib_1.__awaiter(this, void 0, void 0, function* () { return choices; }), false, matched === null || matched === void 0 ? void 0 : matched.version);
            return snapshots.find(s => s.version === selected);
        });
    }
    tagPromptFor(tags, tagNameHint, explicitTagName) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const matched = tagNameHint ? tags.find(t => t.name === tagNameHint) : undefined;
            if (matched && explicitTagName) {
                this._ui.userMessage(`Continuing with tag ${this._styler.hilite(matched.name)}`);
                return matched;
            }
            if (tagNameHint && !matched) {
                this._ui.userMessage(this._styler.colorWarning(`Tag "${tagNameHint}" not found on the selected snapshot.`));
            }
            if (tags.length === 1) {
                this._ui.userMessage(`Continuing with tag ${this._styler.hilite(tags[0].name)}`);
                return tags[0];
            }
            const choices = tags.map(t => ({ name: t.name, value: t.name }));
            const selectedName = yield this._ui.promptSelect("tagName", "Select the tag to remove:", choices);
            return tags.find(t => t.name === selectedName);
        });
    }
    snapshotFormatChoice(s) {
        var _a, _b;
        const d = typeof s.created === 'string' ? new Date(s.created) : s.created;
        const dateStr = d.toISOString().split('T')[0];
        const tagsStr = (_b = (_a = s.tags) === null || _a === void 0 ? void 0 : _a.map((t) => t.name).join(", ")) !== null && _b !== void 0 ? _b : "";
        return `${s.version.padEnd(10)} ${dateStr}${tagsStr ? `  [${tagsStr}]` : ""}`;
    }
}
exports.default = SnapshotUntag;
SnapshotUntag.aliases = ["cluster:stack:untag"];
SnapshotUntag.description = 'Removes a single tag from a snapshot.';
SnapshotUntag.examples = [
    { description: 'Interactive — select a snapshot then select the tag to remove.', command: '<%= config.bin %> <%= command.id %> -e myEnterprise' },
    { description: 'Non-interactive (scripted).', command: '<%= config.bin %> <%= command.id %> -e myEnterprise -v 5CJRH7XB -t production --silent' },
    { description: 'Renders the equivalent silent command and then executes.', command: '<%= config.bin %> <%= command.id %> -e myEnterprise -v 5CJRH7XB -t production --echo' },
    { description: 'Renders the equivalent silent command without executing.', command: '<%= config.bin %> <%= command.id %> -e myEnterprise -v 5CJRH7XB -t production --to-script' },
];
SnapshotUntag.flags = {
    help: core_1.Flags.help({ char: 'h' }),
    enterprise: core_1.Flags.string({ char: 'e', required: false, description: 'Code name of the enterprise containing the target snapshot.' }),
    version: core_1.Flags.string({ char: 'v', required: false, description: 'Version identifier of the snapshot from which to remove a tag (e.g., 5CJRH7XB).' }),
    tag: core_1.Flags.string({ char: 't', required: false, description: 'Name of the tag to remove from the snapshot.' }),
    silent: core_1.Flags.boolean({ exclusive: ["echo", "to-script"], description: 'Executes without any user interaction; fails on missing or invalid arguments.' }),
    echo: core_1.Flags.boolean({ exclusive: ["to-script", "silent"], description: 'Renders the equivalent non-interactive command for future use before executing.' }),
    "to-script": core_1.Flags.boolean({ exclusive: ["echo", "silent"], description: 'Renders the equivalent non-interactive command without executing it.' }),
};
SnapshotUntag.args = {};
//# sourceMappingURL=untag.js.map