"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const codiac_domain_1 = require("@codiac.io/codiac-domain");
const command_base_exec_tenant_1 = require("../../../command-base-exec-tenant");
const _ = require("lodash");
class NocClusterGrant extends command_base_exec_tenant_1.CommandBaseExecTenant {
    captureArgs() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { flags } = yield this.parse(NocClusterGrant);
            return [{}, false];
        });
    }
    buildCandidate_silently(_partial, _rootMap) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { flags } = yield this.parse(NocClusterGrant);
            if (!flags.user || _.isEmpty(flags.user))
                throw new Error(`User (--user / -u) is required in silent mode.`);
            if (!flags.cluster)
                throw new Error(`Cluster (--cluster / -c) is required in silent mode.`);
            const clusterDefs = yield this.loadClusters();
            const found = clusterDefs.find(c => c.name === flags.cluster);
            if (!found)
                throw new Error(`Cluster [${flags.cluster}] does not exist in this tenant.`);
            return { cluster: found, user: flags.user };
        });
    }
    buildCandidate_interactively(_partial, _takeDefaults, _rootMap) {
        var _a;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { flags } = yield this.parse(NocClusterGrant);
            const clusterDefs = yield this.loadClusters();
            if (clusterDefs.length === 0) {
                this._ui.userMessage("No clusters found.");
                return undefined;
            }
            let candidate = {};
            if (flags.cluster) {
                const found = clusterDefs.find(c => c.name === flags.cluster);
                if (found)
                    candidate.cluster = found;
            }
            if (flags.user && !_.isEmpty(flags.user))
                candidate.user = flags.user;
            let confirmed = false;
            do {
                candidate.cluster = yield this.promptForCluster(clusterDefs, (_a = candidate.cluster) === null || _a === void 0 ? void 0 : _a.name);
                candidate.user = yield this.promptForUser(candidate.user);
                this._ui.userMessage(`Granting cluster access on [${this._styler.hilite(candidate.cluster.name)}] to user [${this._styler.hilite(candidate.user)}]`);
                confirmed = yield this._ui.promptConfirm("confirmGrant", `Continue? (Ctrl-C to cancel)`, false);
            } while (!confirmed);
            yield this.cspContextualizer.promptForCloudProviderCreds(this.ioc, candidate.cluster.provider, undefined, undefined, undefined, candidate.cluster.providerSubscription);
            return { cluster: candidate.cluster, user: candidate.user };
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("-c", candidate.cluster.name);
        cmd.push("-u", candidate.user);
        cmd.push("--silent");
        return cmd;
    }
    executeTask(candidate) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            this._ui.startSpinner(`Granting access...`);
            const result = yield this.genRelayClient.Call.grantClusterAccess({ clusterName: candidate.cluster.name, users: [candidate.user] });
            this._ui.stopSpinner(result.success ? "SUCCESS" : "FAILED");
            const msg = `Access grant ${result.success ? this._styler.colorGood("SUCCEEDED") : this._styler.colorCritical("FAILED")}: ${result.message || ""}`;
            this.logger.debug(msg, result);
            this._ui.userMessage(msg);
        });
    }
    describe(cluster) {
        return `${cluster.name} ${this._styler.dim("(" + cluster.provider + (cluster.locationName ? ", " + cluster.locationName : "") + ")")}`;
    }
    loadClusters(csp) {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const crit = { privateOwner: (_a = this._userCntx) === null || _a === void 0 ? void 0 : _a.currentTenantCode };
            const projection = { pathsIncluded: ["id", "name", "provider", "locationName", "privateOwner", "instance"], pathsExcluded: [] };
            const readResult = yield this._codiacApi.ClusterDef.tryReadMany(crit, { projection: projection });
            let clusterDefs = ((_b = readResult.output) !== null && _b !== void 0 ? _b : []).filter(c => c.instance != undefined);
            if (csp && Object.keys(codiac_domain_1.CloudProviderEnum).indexOf(csp) >= 0) {
                clusterDefs = clusterDefs.filter(c => c.provider === csp);
            }
            return _.orderBy(clusterDefs, c => c.name);
        });
    }
    promptForCluster(clusterDefs, defaultValue) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let keep = false;
            if (defaultValue && clusterDefs.find(c => c.name === defaultValue)) {
                keep = yield this._ui.promptConfirm("clusterNameConfirm", `Target Cluster: [${this._styler.hilite(defaultValue)}]`, true);
            }
            if (keep)
                return clusterDefs.find(c => c.name === defaultValue);
            const choices = clusterDefs.map(c => ({ name: this.describe(c), value: c.name }));
            const selectedName = (yield this._ui.promptSelect("clusterName", "Select the target cluster:", choices));
            return clusterDefs.find(c => c.name === selectedName);
        });
    }
    promptForUser(defaultValue) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let keep = false;
            if (defaultValue) {
                keep = yield this._ui.promptConfirm("usernameConfirm", `AWS username: [${this._styler.hilite(defaultValue)}]`, true);
            }
            if (defaultValue && keep)
                return defaultValue;
            return (yield this._ui.prompt("username", "AWS username (email): ", true, defaultValue));
        });
    }
}
exports.default = NocClusterGrant;
NocClusterGrant.description = '(AWS Only) Provides cluster access to the given user.';
NocClusterGrant.aliases = ["cluster:grant"];
NocClusterGrant.flags = {
    help: core_1.Flags.help({ char: 'h' }),
    cluster: core_1.Flags.string({ char: 'c', required: false, description: 'Name of the cluster to grant access on.' }),
    user: core_1.Flags.string({ char: 'u', multiple: false, required: false, description: 'AWS username (as email) to add.' }),
    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.' }),
};
NocClusterGrant.args = {};
NocClusterGrant.examples = [
    { description: "Grant cluster access interactively.", command: "<%= config.bin %> <%= command.id %>" },
    { description: "Non-interactive invocation.", command: "<%= config.bin %> <%= command.id %> -c my-cluster -u user@example.com --silent" },
    { description: "Renders the equivalent silent command without executing.", command: "<%= config.bin %> <%= command.id %> -c my-cluster -u user@example.com --to-script" },
];
//# sourceMappingURL=grant.js.map