"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const YAML = require("yaml");
const jmespath = require("jmespath");
const command_base_exec_1 = require("../../command-base-exec");
const _ = require("lodash");
const render = require("../../uilogic/render-methods");
const render_methods_1 = require("../../uilogic/render-methods");
const type_safety_utils_1 = require("../../uilogic/type-safety-utils");
class SnapshotList extends command_base_exec_1.CommandBaseExec {
    constructor() {
        super(...arguments);
        this.infrxAliases = ["cluster:stack:list"];
        this._outputFormat = render_methods_1.OutputFormatsEnum.tree;
    }
    captureArgs() {
        var _a;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { flags } = yield this.parse(SnapshotList);
            let partial = {};
            if (flags.enterprise)
                partial.enterprise = flags.enterprise;
            this._query = flags.query;
            this._outputFormat = (_a = type_safety_utils_1.TypeSafetyUtils.toEnum(render_methods_1.OutputFormatsEnum, flags.output)) !== null && _a !== void 0 ? _a : render_methods_1.OutputFormatsEnum.tree;
            if (this._query && !flags.output)
                this._outputFormat = render_methods_1.OutputFormatsEnum.json;
            if (this._query && [render_methods_1.OutputFormatsEnum.text, render_methods_1.OutputFormatsEnum.tree].includes(this._outputFormat)) {
                throw new Error("--query is not compatible with --output text or --output tree.");
            }
            return [partial, false];
        });
    }
    buildCandidate_silently(partial, rootMap) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            return { enterprise: partial.enterprise };
        });
    }
    buildCandidate_interactively(partial, rootMap, takeDefaults) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            return { enterprise: partial.enterprise };
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("-e", candidate.enterprise);
        cmd.push("-o", this._outputFormat);
        if (this._query)
            cmd.push("-q", this._query);
        cmd.push("--silent");
        return cmd;
    }
    executeTask(candidate) {
        var _a;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const machineReadable = [render_methods_1.OutputFormatsEnum.json, render_methods_1.OutputFormatsEnum.yaml].includes(this._outputFormat);
            if (!machineReadable)
                this._ui.startSpinner("Retrieving");
            const crit = {
                enterprise: candidate.enterprise,
                take: 20,
                sort: "version~desc"
            };
            const result = yield this._codiacApi.EnterpriseVersionConfig.tryReadMany(crit);
            if (result.error) {
                if (!machineReadable)
                    this._ui.stopSpinner("failed");
                throw result.error;
            }
            const snapshots = (_a = result.output) !== null && _a !== void 0 ? _a : [];
            if (!machineReadable)
                this._ui.stopSpinner(`found ${snapshots.length}`);
            let data = snapshots;
            if (this._query) {
                data = jmespath.search(snapshots, this._query);
            }
            switch (this._outputFormat) {
                case render_methods_1.OutputFormatsEnum.json:
                    const sortedForJson = this._query ? data : _.sortBy(snapshots, s => s.enterprise, s => s.version);
                    this._ui.userMessage(JSON.stringify(sortedForJson, undefined, 2));
                    break;
                case render_methods_1.OutputFormatsEnum.yaml:
                    const sortedForYaml = this._query ? data : _.sortBy(snapshots, s => s.enterprise, s => s.version);
                    this._ui.userMessage(YAML.stringify(sortedForYaml, { indent: 2 }));
                    break;
                case render_methods_1.OutputFormatsEnum.text:
                    this._ui.userMessage(render.renderStringList(this.buildSnapshotListForText(snapshots)));
                    break;
                case render_methods_1.OutputFormatsEnum.tree:
                default:
                    this._ui.userMessage(render.renderStringTree(this.buildSnapshotTree(snapshots)));
                    break;
            }
        });
    }
    buildSnapshotListForText(snapshots) {
        const listForText = [];
        for (const snapshot of _.sortBy(snapshots, s => s.enterprise, s => s.version)) {
            let line = snapshot.enterprise.concat("/", this._styler.hilite(snapshot.version));
            line = line.concat(this._styler.dim(` (${this.renderSnapshotDetails(snapshot)})`));
            listForText.push(line);
            if (snapshot.contents && Array.isArray(snapshot.contents) && snapshot.contents.length > 0) {
                for (const content of snapshot.contents) {
                    const assetName = content.assetName || content.entityName || 'unknown';
                    const assetVersion = content.version || 'unknown';
                    listForText.push(`  └─ ${this._styler.hilite(assetName)} ${this._styler.dim(`(${assetVersion})`)}`);
                }
            }
        }
        return listForText;
    }
    renderSnapshotDetails(snapshot) {
        let details = `created: ${this.formatDate(snapshot.created)}`;
        if (snapshot.contents && Array.isArray(snapshot.contents) && snapshot.contents.length > 0) {
            details = details.concat(`, ${snapshot.contents.length} asset${snapshot.contents.length !== 1 ? 's' : ''}`);
        }
        if (snapshot.contentHash) {
            details = details.concat(`, hash: ${snapshot.contentHash.substring(0, 8)}...`);
        }
        return details;
    }
    formatDate(date) {
        if (date instanceof Date)
            return date.toISOString().split('T')[0];
        return new Date(date).toISOString().split('T')[0];
    }
    buildSnapshotTree(snapshots) {
        const tree = [];
        const byEnterprise = _.groupBy(snapshots, s => s.enterprise);
        for (const enterprise of Object.keys(byEnterprise).sort()) {
            const entSnapshots = byEnterprise[enterprise];
            const entBranch = { text: `Enterprise: ${enterprise}` };
            for (const snapshot of _.sortBy(entSnapshots, s => s.version)) {
                let text = this._styler.hilite(snapshot.version);
                if (snapshot.contents && Array.isArray(snapshot.contents) && snapshot.contents.length > 0) {
                    text = text.concat(` (${snapshot.contents.length} asset${snapshot.contents.length !== 1 ? 's' : ''})`);
                }
                text = text.concat(` - Tagged by: ${snapshot.createdBy}`);
                text = text.concat(` - Date: ${this.formatDate(snapshot.created)}`);
                if (entBranch.children === undefined)
                    entBranch.children = [];
                entBranch.children.push({ text });
            }
            tree.push(entBranch);
        }
        return tree;
    }
}
exports.default = SnapshotList;
SnapshotList.description = 'Shows the list of snapshots (enterprise version configs) in a given enterprise.';
SnapshotList.aliases = ["cluster:stack:list"];
SnapshotList.flags = {
    help: core_1.Flags.help({ char: 'h' }),
    enterprise: core_1.Flags.string({ char: 'e', required: false, description: 'The name of the enterprise containing the snapshots (defaults to the current enterprise context).' }),
    output: core_1.Flags.string({ char: 'o', description: "Format in which to render the results (defaults to tree).", options: [render_methods_1.OutputFormatsEnum.json, render_methods_1.OutputFormatsEnum.yaml, render_methods_1.OutputFormatsEnum.tree, render_methods_1.OutputFormatsEnum.text] }),
    query: core_1.Flags.string({ char: 'q', description: "JMESPath expression to filter or reshape the results (see jmespath.org)." }),
    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.' }),
};
SnapshotList.args = {};
SnapshotList.examples = [
    { description: "List all snapshots for the current enterprise.", command: "<%= config.bin %> <%= command.id %>" },
    { description: "List snapshots for a specific enterprise.", command: "<%= config.bin %> <%= command.id %> -e myEnterprise" },
    { description: "List snapshot versions only.", command: "<%= config.bin %> <%= command.id %> -q '[].version'" },
    { description: "Export as YAML.", command: "<%= config.bin %> <%= command.id %> -o yaml" },
    { description: "Non-interactive (scripted) invocation.", command: "<%= config.bin %> <%= command.id %> -e myEnterprise --silent" },
];
//# sourceMappingURL=list.js.map