"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const command_base_exec_tenant_1 = require("../../../command-base-exec-tenant");
class NocClusterRestore extends command_base_exec_tenant_1.CommandBaseExecTenant {
    captureArgs() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { args, flags } = yield this.parse(NocClusterRestore);
            const partial = {
                clusterName: args.name,
                skipProvision: flags['no-provision'],
                skipAgent: flags['no-agent'],
                skipInfrx: flags['no-infrx'],
                skipCabinets: flags['no-cabinets'],
                enterprise: flags.enterprise,
            };
            return [partial, false];
        });
    }
    buildCandidate_silently(partial, _rootMap) {
        var _a, _b, _c, _d, _e;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (!partial.clusterName)
                throw new Error('Cluster name argument is required in silent mode.');
            const found = yield this._codiacApi.ClusterDef.tryReadMany({
                name: { $eq: partial.clusterName },
                privateOwner: this._userCntx.currentTenantCode,
            });
            if (found.error)
                throw found.error;
            if (!((_a = found.output) === null || _a === void 0 ? void 0 : _a.length))
                throw new Error(`No cluster exists named [${partial.clusterName}].`);
            return {
                clusterName: partial.clusterName,
                skipProvision: (_b = partial.skipProvision) !== null && _b !== void 0 ? _b : false,
                skipAgent: (_c = partial.skipAgent) !== null && _c !== void 0 ? _c : false,
                skipInfrx: (_d = partial.skipInfrx) !== null && _d !== void 0 ? _d : false,
                skipCabinets: (_e = partial.skipCabinets) !== null && _e !== void 0 ? _e : false,
                enterprise: partial.enterprise,
            };
        });
    }
    buildCandidate_interactively(partial, _takeDefaults, rootMap) {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { flags } = yield this.parse(NocClusterRestore);
            // Select cluster
            let clusterName = partial.clusterName;
            if (!clusterName) {
                const clusters = (_a = rootMap.clusters) !== null && _a !== void 0 ? _a : [];
                if (clusters.length === 0) {
                    this._ui.userMessage('No clusters are available to restore.');
                    return undefined;
                }
                const choices = clusters.map(c => ({ name: c.name, value: c.name }));
                clusterName = (yield this._ui.promptSelect('cluster', 'Select cluster to restore:', choices, false, false));
            }
            // Load ClusterDef to check isCaptured
            const found = yield this._codiacApi.ClusterDef.tryReadMany({
                name: { $eq: clusterName },
                privateOwner: this._userCntx.currentTenantCode,
            });
            if (found.error)
                throw found.error;
            const clusterDef = (_b = found.output) === null || _b === void 0 ? void 0 : _b[0];
            if (!clusterDef) {
                this._ui.userMessage(`Cluster [${clusterName}] was not found.`);
                return undefined;
            }
            // Warn if captured cluster
            if (clusterDef.isCaptured) {
                this._ui.userMessage(this._styler.colorWarning(`Warning: [${clusterName}] is a captured cluster. Its lifecycle may be managed externally. ` +
                    `Restoring it here could conflict with its source environment.`));
                const proceed = yield this._ui.promptConfirm('confirmCaptured', 'Proceed anyway?', false);
                if (!proceed)
                    return undefined;
            }
            // Warn if cluster already has a live instance and provision is not being skipped
            if (clusterDef.instance && !flags['no-provision']) {
                this._ui.userMessage(this._styler.colorWarning(`Warning: [${clusterName}] already has a running instance. ` +
                    `Restoring requires destroying it first (\`cod cluster destroy ${clusterName}\`). ` +
                    `To re-run bootstrap only on the existing cluster, use --no-provision.`));
                const proceed = yield this._ui.promptConfirm('confirmInstance', 'Continue anyway?', false);
                if (!proceed)
                    return undefined;
            }
            return {
                clusterName,
                skipProvision: flags['no-provision'],
                skipAgent: flags['no-agent'],
                skipInfrx: flags['no-infrx'],
                skipCabinets: flags['no-cabinets'],
                enterprise: flags.enterprise,
            };
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push(candidate.clusterName);
        if (candidate.skipProvision)
            cmd.push('--no-provision');
        if (candidate.skipAgent)
            cmd.push('--no-agent');
        if (candidate.skipInfrx)
            cmd.push('--no-infrx');
        if (candidate.skipCabinets)
            cmd.push('--no-cabinets');
        if (candidate.enterprise)
            cmd.push('--enterprise', candidate.enterprise);
        cmd.push('--silent');
        return cmd;
    }
    executeTask(candidate) {
        var _a, _b, _c;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const result = yield this.watcher.triggerAndWatch((correlationId, socketId) => this.genRelayClient.Call.clusterRestoreAsync({
                clusterName: candidate.clusterName,
                skipProvision: candidate.skipProvision || undefined,
                skipAgent: candidate.skipAgent || undefined,
                skipInfrx: candidate.skipInfrx || undefined,
                skipCabinets: candidate.skipCabinets || undefined,
                enterprise: candidate.enterprise,
                socketId,
                correlationId,
            }));
            if (result.error) {
                const msg = `Error restoring cluster [${candidate.clusterName}]: ${(_a = result.message) !== null && _a !== void 0 ? _a : ''} ${(_b = result.error.message) !== null && _b !== void 0 ? _b : ''}`.trimEnd();
                this.logger.error(msg, result.error);
                this._ui.userMessage(`${this._styler.colorCritical('ERROR!')} ${msg}`);
            }
            else if (!result.success) {
                const msg = `Restore failed for cluster [${candidate.clusterName}]: ${(_c = result.message) !== null && _c !== void 0 ? _c : ''}`.trimEnd();
                this.logger.notice(msg, result);
                this._ui.userMessage(`${this._styler.colorCritical('FAILED!')} ${msg}`);
            }
            else {
                this._ui.userMessage(`${this._styler.colorGood('SUCCESS!')} Restore complete for cluster [${this._styler.hilite(candidate.clusterName)}].`);
            }
        });
    }
}
exports.default = NocClusterRestore;
NocClusterRestore.description = 'Restores a cluster to fully operational state from its existing ClusterDef: ' +
    'provisions cloud infrastructure, installs the Codiac agent, installs infrx stacks, ' +
    'and restores all SDLC cabinets. Pass --no-provision to re-run bootstrap only on an ' +
    'already-provisioned cluster.';
NocClusterRestore.aliases = ['cluster:restore'];
NocClusterRestore.flags = {
    'no-provision': core_1.Flags.boolean({
        default: false,
        description: 'Skip cloud infrastructure provisioning. The cluster must already have a live instance. Use this to re-run bootstrap on an existing cluster.',
    }),
    'no-agent': core_1.Flags.boolean({
        default: false,
        description: 'Skip Codiac agent installation. Also skips infrx and cabinet restore.',
    }),
    'no-infrx': core_1.Flags.boolean({
        default: false,
        description: 'Skip infrx stack installation. Also skips cabinet restore.',
    }),
    'no-cabinets': core_1.Flags.boolean({
        default: false,
        description: 'Skip SDLC cabinet restore. Provision, agent, and infrx still run.',
    }),
    enterprise: core_1.Flags.string({
        char: 'e',
        description: 'Scope cabinet restore to a specific enterprise. When omitted, all enterprises are restored.',
    }),
    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 command before executing.',
    }),
    'to-script': core_1.Flags.boolean({
        exclusive: ['echo', 'silent'],
        description: 'Renders the equivalent non-interactive command without executing.',
    }),
};
NocClusterRestore.args = {
    name: core_1.Args.string({ description: 'Name of the cluster to restore.' }),
};
NocClusterRestore.examples = [
    { description: 'Full restore interactively.', command: '<%= config.bin %> <%= command.id %>' },
    { description: 'Full restore of a specific cluster.', command: '<%= config.bin %> <%= command.id %> prod-cluster-1 --silent' },
    { description: 'Re-run bootstrap only (cluster already provisioned).', command: '<%= config.bin %> <%= command.id %> prod-cluster-1 --no-provision --silent' },
    { description: 'Provision and agent only (skip infrx and cabinets).', command: '<%= config.bin %> <%= command.id %> prod-cluster-1 --no-infrx --no-cabinets --silent' },
    { description: 'Restore scoped to one enterprise.', command: '<%= config.bin %> <%= command.id %> prod-cluster-1 --enterprise acme --silent' },
    { description: 'Render the equivalent silent command without executing.', command: '<%= config.bin %> <%= command.id %> prod-cluster-1 --to-script' },
];
//# sourceMappingURL=restore.js.map