"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const _ = require("lodash");
const command_base_exec_tenant_1 = require("../../command-base-exec-tenant");
class CabinetRestore extends command_base_exec_tenant_1.CommandBaseExecTenant {
    captureArgs() {
        var _a;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { flags } = yield this.parse(CabinetRestore);
            if (flags.cluster && flags.cabinet) {
                throw new Error("Cannot use --cluster and --cabinet together. Use one or the other.");
            }
            let partial = {};
            if (flags.cluster) {
                partial = { mode: 'cluster', cluster: flags.cluster, enterprise: flags.enterprise };
            }
            else if ((_a = flags.cabinet) === null || _a === void 0 ? void 0 : _a.length) {
                if (!flags.environment && !flags.enterprise)
                    throw new Error("When using --cabinet, provide --environment (and optionally --enterprise).");
                partial = {
                    mode: 'cabinets',
                    cabinets: flags.cabinet.map(cab => {
                        var _a, _b;
                        return ({
                            cabinet: cab,
                            enterprise: (_a = flags.enterprise) !== null && _a !== void 0 ? _a : "",
                            environment: (_b = flags.environment) !== null && _b !== void 0 ? _b : "",
                        });
                    })
                };
            }
            const takeDefaults = flags['take-defaults'];
            return [partial, takeDefaults];
        });
    }
    buildCandidate_silently(partial, rootMap) {
        var _a, _b, _c;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (!partial.mode)
                throw new Error("Must provide either --cluster or --cabinet.");
            if (partial.mode === 'cluster') {
                if (!partial.cluster || _.isEmpty(partial.cluster))
                    throw new Error("Missing --cluster argument.");
                const found = (_a = rootMap.clusters) === null || _a === void 0 ? void 0 : _a.find(c => c.name === partial.cluster);
                if (!found)
                    throw new Error(`Cluster [${partial.cluster}] was not found.`);
                return { mode: 'cluster', cluster: partial.cluster, enterprise: partial.enterprise };
            }
            if (!((_b = partial.cabinets) === null || _b === void 0 ? void 0 : _b.length))
                throw new Error("No cabinets specified.");
            // Validate each cabinet exists
            for (const item of partial.cabinets) {
                if (!item.enterprise)
                    throw new Error(`Missing enterprise for cabinet [${item.cabinet}].`);
                if (!item.environment)
                    throw new Error(`Missing environment for cabinet [${item.cabinet}].`);
                const ent = rootMap.enterprises.find(e => e.name === item.enterprise);
                if (!ent)
                    throw new Error(`Enterprise [${item.enterprise}] was not found.`);
                const env = ent.environments.find(e => e.name === item.environment);
                if (!env)
                    throw new Error(`Environment [${item.environment}] was not found.`);
                const cab = (_c = env.cabinets) === null || _c === void 0 ? void 0 : _c.find(c => c.name === item.cabinet);
                if (!cab)
                    throw new Error(`Cabinet [${item.cabinet}] was not found in [${item.enterprise}/${item.environment}].`);
            }
            return { mode: 'cabinets', cabinets: partial.cabinets };
        });
    }
    buildCandidate_interactively(partial, takeDefaults, rootMap) {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            // Ask: restore by cluster or by explicit cabinet list?
            if (!partial.mode) {
                const mode = yield this._ui.promptSelect("mode", "Restore by:", [
                    { name: "All cabinets on a cluster", value: "cluster" },
                    { name: "Explicit cabinet list", value: "cabinets" },
                ], false, false);
                partial.mode = mode;
            }
            if (partial.mode === 'cluster') {
                if (!partial.cluster) {
                    const clusterChoices = ((_a = rootMap.clusters) !== null && _a !== void 0 ? _a : []).map(c => ({ name: c.name, value: c.name }));
                    partial.cluster = (yield this._ui.promptSelect("cluster", "Cluster: ", clusterChoices, false, false));
                }
                return { mode: 'cluster', cluster: partial.cluster, enterprise: partial.enterprise };
            }
            // Interactive cabinet selection: pick one or more cabinets
            const cabinets = (_b = partial.cabinets) !== null && _b !== void 0 ? _b : [];
            const addAnother = () => tslib_1.__awaiter(this, void 0, void 0, function* () {
                const entChoices = rootMap.enterprises.map(e => ({ name: e.name, value: e.name }));
                const enterprise = (yield this._ui.promptSelect("enterprise", "Enterprise: ", entChoices, false, false));
                const [cab] = yield this.rootMapUtils.promptForCabinet(enterprise, rootMap, undefined, false, this.rootMapUtils.clusterLabelEmbellisher());
                cabinets.push({ cabinet: cab.name, enterprise: cab.enterprise, environment: cab.environment });
                const more = yield this._ui.promptConfirm("addAnother", "Add another cabinet?", false);
                if (more)
                    yield addAnother();
            });
            yield addAnother();
            return { mode: 'cabinets', cabinets };
        });
    }
    buildCommandString(candidate, cmd) {
        var _a;
        if (candidate.mode === 'cluster') {
            cmd.push("--cluster", candidate.cluster);
            if (candidate.enterprise)
                cmd.push("--enterprise", candidate.enterprise);
        }
        else {
            for (const item of (_a = candidate.cabinets) !== null && _a !== void 0 ? _a : []) {
                cmd.push("--cabinet", item.cabinet);
                cmd.push("--enterprise", item.enterprise);
                cmd.push("--environment", item.environment);
            }
        }
        cmd.push("--silent");
        return cmd;
    }
    executeTask(candidate) {
        var _a, _b, _c, _d, _e;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const label = candidate.mode === 'cluster'
                ? `cluster [${candidate.cluster}]`
                : `${(_b = (_a = candidate.cabinets) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0} cabinet(s)`;
            const result = yield this.watcher.triggerAndWatch((correlationId, socketId) => this.genRelayClient.Call.cabinetRestore(Object.assign(Object.assign({}, (candidate.mode === 'cluster'
                ? { cluster: candidate.cluster, enterprise: candidate.enterprise }
                : { cabinets: candidate.cabinets })), { socketId,
                correlationId })));
            if (result.error) {
                const msg = `Error restoring ${label}: ${(_c = result.message) !== null && _c !== void 0 ? _c : ""} ${(_d = result.error.message) !== null && _d !== void 0 ? _d : ""}`.trimEnd();
                this.logger.error(msg, result.error);
                this._ui.userMessage(`${this._styler.colorCritical("ERROR!")} ${msg}`);
            }
            else if (!result.success) {
                const msg = `Cabinet restore failed for ${label}: ${(_e = result.message) !== null && _e !== void 0 ? _e : ""}`.trimEnd();
                this.logger.notice(msg, result);
                this._ui.userMessage(`${this._styler.colorCritical("FAILED!")} ${msg}`);
            }
            else {
                const msg = `${this._styler.colorGood("SUCCESS!")} Restore complete for ${label}.`;
                this.logger.notice(msg, result);
                this._ui.userMessage(msg);
            }
        });
    }
}
exports.default = CabinetRestore;
CabinetRestore.description = 'Brings one or more cabinets back to a live state on their assigned cluster: records the cluster assignment, provisions the Kubernetes namespace, and deploys the enterprise version stamped on the cabinet (if any). Accepts either an explicit cabinet list or a cluster shorthand that targets all cabinets on the cluster at once.';
CabinetRestore.aliases = ["cab:restore"];
CabinetRestore.examples = [
    { description: 'Restore all cabinets on a cluster interactively.', command: '<%= config.bin %> <%= command.id %>' },
    { description: 'Restore all cabinets on a specific cluster (all enterprises).', command: '<%= config.bin %> <%= command.id %> --cluster prod-cluster-1' },
    { description: 'Restore all cabinets on a cluster scoped to one enterprise.', command: '<%= config.bin %> <%= command.id %> --cluster prod-cluster-1 --enterprise acme' },
    { description: 'Restore a single explicit cabinet.', command: '<%= config.bin %> <%= command.id %> --cabinet api-gateway --enterprise acme --environment prod' },
    { description: 'Restore multiple explicit cabinets in one operation.', command: '<%= config.bin %> <%= command.id %> --cabinet api-gateway --cabinet auth-service --enterprise acme --environment prod' },
    { description: 'Non-interactive (scripted) cluster restore — fails fast on any missing argument.', command: '<%= config.bin %> <%= command.id %> --cluster prod-cluster-1 --enterprise acme --silent' },
    { description: 'Renders the equivalent silent command and then executes (useful for building scripts).', command: '<%= config.bin %> <%= command.id %> --cluster prod-cluster-1 --echo' },
    { description: 'Renders the equivalent silent command without executing (dry run).', command: '<%= config.bin %> <%= command.id %> --cluster prod-cluster-1 --to-script' },
];
CabinetRestore.flags = {
    cluster: core_1.Flags.string({ char: 'c', description: 'Restore all cabinets on this cluster (mutually exclusive with --cabinet).' }),
    cabinet: core_1.Flags.string({ char: 'b', multiple: true, description: 'Name of a cabinet to restore. Repeat for multiple. Mutually exclusive with --cluster.' }),
    enterprise: core_1.Flags.string({ char: 'e', description: 'Scope restore to this enterprise (only used with --cluster).' }),
    environment: core_1.Flags.string({ char: 'n', description: 'Environment of the cabinet (required when using --cabinet without --cluster).' }),
    silent: core_1.Flags.boolean({ exclusive: ["echo", "to-script"], description: 'Non-Interactive mode; executes without any user interaction and fails on any missing or invalid arguments.' }),
    echo: core_1.Flags.boolean({ exclusive: ["to-script", "silent"], description: 'Echo interaction mode; renders the equivalent non-interactive cli command for future use before final execution.' }),
    "to-script": core_1.Flags.boolean({ exclusive: ["echo", "silent"], description: 'Toscript interaction mode; renders the equivalent non-interactive cli command WITHOUT any execution.' }),
    "take-defaults": core_1.Flags.boolean({ exclusive: ["silent"], description: "Prevents prompting for confirmation on parameters that were passed in or were automatically set to default values (Irrelevant in --silent mode)." })
};
CabinetRestore.args = {};
//# sourceMappingURL=restore.js.map