// SPDX-License-Identifier: Apache-2.0
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
var DefaultOneShotCommand_1;
import { Listr } from 'listr2';
import { SoloError } from '../../core/errors/solo-error.js';
import * as constants from '../../core/constants.js';
import { BaseCommand } from '../base.js';
import { Flags as flags, Flags } from '../flags.js';
import { inject, injectable } from 'tsyringe-neo';
import { NamespaceName } from '../../types/namespace/namespace-name.js';
import { StringEx } from '../../business/utils/string-ex.js';
import * as version from '../../../version.js';
import { confirm as confirmPrompt, select as selectPrompt } from '@inquirer/prompts';
import { ClusterReferenceCommandDefinition } from '../command-definitions/cluster-reference-command-definition.js';
import { DeploymentCommandDefinition } from '../command-definitions/deployment-command-definition.js';
import { ConsensusCommandDefinition } from '../command-definitions/consensus-command-definition.js';
import { KeysCommandDefinition } from '../command-definitions/keys-command-definition.js';
import { MirrorCommandDefinition } from '../command-definitions/mirror-command-definition.js';
import { ExplorerCommandDefinition } from '../command-definitions/explorer-command-definition.js';
import { RelayCommandDefinition } from '../command-definitions/relay-command-definition.js';
import { patchInject } from '../../core/dependency-injection/container-helper.js';
import { InjectTokens } from '../../core/dependency-injection/inject-tokens.js';
import { PREDEFINED_ACCOUNT_GROUPS, predefinedEcdsaAccountsWithAlias, } from './predefined-accounts.js';
import { AccountId, HbarUnit, PublicKey, TopicCreateTransaction, TopicId, TopicInfoQuery, } from '@hiero-ledger/sdk';
import * as helpers from '../../core/helpers.js';
import { createDirectoryIfNotExists, entityId, remoteConfigsToDeploymentsTable } from '../../core/helpers.js';
import { Duration } from '../../core/time/duration.js';
import { resolveNamespaceFromDeployment } from '../../core/resolvers.js';
import fs from 'node:fs';
import path from 'node:path';
import chalk from 'chalk';
import { PathEx } from '../../business/utils/path-ex.js';
import yaml from 'yaml';
import { BlockCommandDefinition } from '../command-definitions/block-command-definition.js';
import { SharedResourceManager } from '../../core/shared-resources/shared-resource-manager.js';
import { argvPushGlobalFlags, invokeSoloCommand, newArgv, optionFromFlag } from '../command-helpers.js';
import { Templates } from '../../core/templates.js';
import { ListrInquirerPromptAdapter } from '@listr2/prompt-adapter-inquirer';
import { SemanticVersion } from '../../business/utils/semantic-version.js';
import { ListrLock } from '../../core/lock/listr-lock.js';
import { ResourceNotFoundError } from '../../integration/kube/errors/resource-operation-errors.js';
import { NoKubeConfigContextError } from '../../business/runtime-state/errors/no-kube-config-context-error.js';
import { DeploymentPhase } from '../../data/schema/model/remote/deployment-phase.js';
import { ComponentTypes } from '../../core/config/remote/enumerations/component-types.js';
let DefaultOneShotCommand = class DefaultOneShotCommand extends BaseCommand {
    static { DefaultOneShotCommand_1 = this; }
    accountManager;
    sharedResourceManager;
    static SINGLE_DEPLOY_CONFIGS_NAME = 'singleAddConfigs';
    static SINGLE_DESTROY_CONFIGS_NAME = 'singleDestroyConfigs';
    _isRollback = false;
    static DEPLOY_FLAGS_LIST = {
        required: [],
        optional: [
            flags.quiet,
            flags.force,
            flags.deployment,
            flags.namespace,
            flags.clusterRef,
            flags.minimalSetup,
            flags.rollback,
            flags.parallelDeploy,
        ],
    };
    static MULTI_DEPLOY_FLAGS_LIST = {
        required: [],
        optional: [...DefaultOneShotCommand_1.DEPLOY_FLAGS_LIST.optional, flags.numberOfConsensusNodes],
    };
    static DESTROY_FLAGS_LIST = {
        required: [],
        optional: [flags.quiet, flags.deployment],
    };
    static FALCON_DEPLOY_FLAGS_LIST = {
        required: [],
        optional: [
            flags.quiet,
            flags.force,
            flags.valuesFile,
            flags.numberOfConsensusNodes,
            flags.deployment,
            flags.namespace,
            flags.clusterRef,
            flags.deployMirrorNode,
            flags.deployExplorer,
            flags.deployRelay,
            flags.rollback,
            flags.parallelDeploy,
        ],
    };
    static FALCON_DESTROY_FLAGS_LIST = {
        required: [],
        optional: [...DefaultOneShotCommand_1.DESTROY_FLAGS_LIST.optional],
    };
    static INFO_FLAGS_LIST = {
        required: [],
        optional: [flags.quiet, flags.deployment],
    };
    constructor(accountManager, sharedResourceManager) {
        super();
        this.accountManager = accountManager;
        this.sharedResourceManager = sharedResourceManager;
        this.accountManager = patchInject(accountManager, InjectTokens.AccountManager, this.constructor.name);
        this.sharedResourceManager = patchInject(sharedResourceManager, InjectTokens.SharedResourceManager, this.constructor.name);
    }
    /**
     * Concatenates a default config file with an override file, writing the result to outputFilePath.
     * Later entries in the file override earlier ones, so the override values take precedence.
     */
    concatConfigFiles(defaultFilePath, overrideFilePath, outputFilePath) {
        const defaultContent = fs.existsSync(defaultFilePath) ? fs.readFileSync(defaultFilePath, 'utf8') : '';
        const overrideContent = fs.existsSync(overrideFilePath) ? fs.readFileSync(overrideFilePath, 'utf8') : '';
        const outputDirectory = path.dirname(outputFilePath);
        if (!fs.existsSync(outputDirectory)) {
            fs.mkdirSync(outputDirectory, { recursive: true });
        }
        fs.writeFileSync(outputFilePath, defaultContent.trimEnd() + '\n' + overrideContent);
        return outputFilePath;
    }
    /**
     * Appends non-empty config entries to the argv array as CLI flags.
     * @param argv - The argument array to append to
     * @param configSection - The config object to extract key-value pairs from
     */
    appendConfigToArgv(argv, configSection) {
        if (!configSection) {
            return;
        }
        for (const [key, value] of Object.entries(configSection)) {
            if (value !== undefined && value !== null && value !== StringEx.EMPTY && key !== '--deployment') {
                argv.push(`${key}`, value.toString());
            }
        }
    }
    async deploy(argv) {
        return this.deployInternal(argv, DefaultOneShotCommand_1.DEPLOY_FLAGS_LIST);
    }
    async deployFalcon(argv) {
        return this.deployInternal(argv, DefaultOneShotCommand_1.FALCON_DEPLOY_FLAGS_LIST);
    }
    async performRollback(deployError, config) {
        if (!config) {
            throw new SoloError(`Deploy failed: ${deployError.message}. Rollback skipped: no resources created.`, deployError);
        }
        if (config.rollback === false) {
            this.logger.warn('Automatic rollback skipped (--no-rollback flag provided)');
            this.logger.warn('To clean up: solo one-shot single destroy');
            this.logger.warn(`Or: kubectl delete ns ${config.namespace.name}`);
            throw new SoloError(`Deploy failed: ${deployError.message}. Rollback skipped (--no-rollback).`, deployError);
        }
        this.logger.warn(`Deploy failed. Starting automatic rollback for deployment '${config.deployment}' in namespace '${config.namespace.name}'...`);
        const destroyArgv = {
            _: [],
            deployment: config.deployment,
            clusterRef: config.clusterRef,
            namespace: config.namespace.name,
            context: config.context,
            quiet: true,
        };
        this._isRollback = true;
        try {
            await this.destroyInternal(destroyArgv, DefaultOneShotCommand_1.DESTROY_FLAGS_LIST);
        }
        catch (rollbackError) {
            this.logger.error(`Rollback failed for deployment '${config.deployment}': ${rollbackError.message}`);
            throw new SoloError(`Deploy failed: ${deployError.message}. Rollback also failed: ${rollbackError.message}`, deployError);
        }
        finally {
            // Safety net: ensure namespace is always deleted during rollback, even if destroyInternal
            // failed or skipped namespace cleanup (e.g. due to skipAll, helm uninstall failure, etc.)
            try {
                const k8 = this.k8Factory.getK8(config.context);
                if (await k8.namespaces().has(config.namespace)) {
                    this.logger.warn(`Rollback cleanup: deleting namespace '${config.namespace.name}'`);
                    await k8.namespaces().delete(config.namespace);
                }
            }
            catch (cleanupError) {
                this.logger.warn(`Failed to delete namespace '${config.namespace.name}' during rollback cleanup: ${cleanupError.message}`);
            }
            this._isRollback = false;
        }
        this.logger.info(`Rollback complete. Cache preserved at: ${config.cacheDir}`);
        throw new SoloError(`Deploy failed: ${deployError.message}. Rollback completed successfully.`, deployError);
    }
    async deployInternal(argv, flagsList) {
        let config = undefined;
        let oneShotLease;
        const mirrorNodeId = 1;
        const tasks = this.taskList.newOneShotSingleDeployTaskList([
            {
                title: 'Initialize',
                task: async (context_, task) => {
                    this.configManager.update(argv);
                    this.oneShotState.activate();
                    const edgeEnabled = this.configManager.getFlag(Flags.edgeEnabled);
                    const versions = this.resolveOneShotComponentVersions(edgeEnabled);
                    // Pre-set component version flags in configManager so they are available
                    // for all sub-commands during concurrent execution
                    this.configManager.setFlag(Flags.releaseTag, versions.consensus);
                    this.configManager.setFlag(Flags.blockNodeChartVersion, versions.blockNode);
                    this.configManager.setFlag(Flags.mirrorNodeVersion, versions.mirror);
                    this.configManager.setFlag(Flags.relayReleaseTag, versions.relay);
                    this.configManager.setFlag(Flags.explorerVersion, versions.explorer);
                    this.configManager.setFlag(Flags.soloChartVersion, versions.soloChart);
                    flags.disablePrompts(flagsList.optional);
                    const allFlags = [...flagsList.required, ...flagsList.optional];
                    await this.configManager.executePrompt(task, allFlags);
                    context_.config = this.configManager.getConfig(DefaultOneShotCommand_1.SINGLE_DEPLOY_CONFIGS_NAME, allFlags);
                    config = context_.config;
                    // Initialize component config sections to empty objects to prevent undefined errors
                    config.consensusNodeConfiguration = {};
                    config.mirrorNodeConfiguration = {};
                    config.blockNodeConfiguration = {};
                    config.explorerNodeConfiguration = {};
                    config.relayNodeConfiguration = {};
                    config.networkConfiguration = {};
                    config.setupConfiguration = {};
                    config.versions = versions;
                    config.cacheDir ??= constants.SOLO_CACHE_DIR;
                    // if valuesFile is set, read the yaml file and save flags to different config sections to be used
                    // later for consensus node, mirror node, block node, explorer node, relay node
                    if (config.valuesFile) {
                        const valuesFileContent = fs.readFileSync(context_.config.valuesFile, 'utf8');
                        const profileItems = yaml.parse(valuesFileContent);
                        // Override with values from file if they exist
                        if (profileItems.network) {
                            config.networkConfiguration = profileItems.network;
                        }
                        if (profileItems.setup) {
                            config.setupConfiguration = profileItems.setup;
                        }
                        if (profileItems.consensusNode) {
                            config.consensusNodeConfiguration = profileItems.consensusNode;
                        }
                        if (profileItems.mirrorNode) {
                            config.mirrorNodeConfiguration = profileItems.mirrorNode;
                        }
                        if (profileItems.blockNode) {
                            config.blockNodeConfiguration = profileItems.blockNode;
                        }
                        if (profileItems.explorerNode) {
                            config.explorerNodeConfiguration = profileItems.explorerNode;
                        }
                        if (profileItems.relayNode) {
                            config.relayNodeConfiguration = profileItems.relayNode;
                        }
                    }
                    config.clusterRef = config.clusterRef || 'one-shot';
                    config.context = config.context || this.k8Factory.default().contexts().readCurrent();
                    config.deployment = config.deployment || 'one-shot';
                    config.namespace = config.namespace || NamespaceName.of('one-shot');
                    this.configManager.setFlag(flags.namespace, config.namespace);
                    config.numberOfConsensusNodes = config.numberOfConsensusNodes || 1;
                    config.force = argv.force;
                    // Apply small-memory node configuration only for CN >= 0.72.0 and when not using `one-shot falcon deploy`
                    const MINIMUM_CN_VERSION_FOR_SMALL_MEMORY = 'v0.72.0-0';
                    const MINIMUM_CN_VERSION_FOR_STATE_ON_DISK = 'v0.73.0-0';
                    const cnVersion = new SemanticVersion(versions.consensus);
                    if (!config.valuesFile && cnVersion.greaterThanOrEqual(MINIMUM_CN_VERSION_FOR_SMALL_MEMORY)) {
                        const defaultsDirectory = PathEx.join(constants.SOLO_CACHE_DIR, 'templates');
                        const overridesDirectory = PathEx.join(defaultsDirectory, 'small-memory');
                        const stateOnDiskDirectory = PathEx.join(defaultsDirectory, 'small-memory-state-on-disk');
                        const mergedDirectory = PathEx.join(defaultsDirectory, 'small-memory-merged');
                        const settingsOverrideFile = config.numberOfConsensusNodes > 1 ? 'settings-multinode.txt' : 'settings-single.txt';
                        const useStateOnDisk = cnVersion.greaterThanOrEqual(MINIMUM_CN_VERSION_FOR_STATE_ON_DISK);
                        const settingsMergedPath = PathEx.join(mergedDirectory, 'settings.txt');
                        // Merge default settings with small-memory overrides
                        this.concatConfigFiles(PathEx.join(defaultsDirectory, 'settings.txt'), PathEx.join(overridesDirectory, settingsOverrideFile), settingsMergedPath);
                        // For CN >= 0.73.0, append state-on-disk settings
                        config.networkConfiguration['--settings-txt'] = useStateOnDisk
                            ? this.concatConfigFiles(settingsMergedPath, PathEx.join(stateOnDiskDirectory, 'settings.txt'), settingsMergedPath)
                            : settingsMergedPath;
                        config.networkConfiguration['--application-properties'] = this.concatConfigFiles(PathEx.join(defaultsDirectory, 'application.properties'), PathEx.join(overridesDirectory, 'application.properties'), PathEx.join(mergedDirectory, 'application.properties'));
                        // For CN >= 0.73.0, use state-on-disk application.env instead of default small-memory
                        config.networkConfiguration['--application-env'] = useStateOnDisk
                            ? PathEx.join(stateOnDiskDirectory, 'application.env')
                            : PathEx.join(overridesDirectory, 'application.env');
                        const throttlesFile = PathEx.join(overridesDirectory, 'throttles.json');
                        if (fs.existsSync(throttlesFile)) {
                            config.networkConfiguration['--genesis-throttles-file'] = throttlesFile;
                        }
                    }
                    // Initialize deployment toggles with defaults if not specified
                    config.deployMirrorNode = config.deployMirrorNode === undefined ? true : config.deployMirrorNode;
                    config.deployExplorer = config.deployExplorer === undefined ? true : config.deployExplorer;
                    config.deployRelay = config.deployRelay === undefined ? true : config.deployRelay;
                    context_.createdAccounts = [];
                    this.logger.debug(`quiet: ${config.quiet}`);
                    return;
                },
            },
            {
                title: 'Acquire deployment lock',
                task: async (_, task) => {
                    oneShotLease = await this.leaseManager.create();
                    return ListrLock.newAcquireLockTask(oneShotLease, task);
                },
            },
            {
                title: 'Check for other deployments',
                task: async (_, task) => {
                    const existingRemoteConfigs = await this.k8Factory
                        .default()
                        .configMaps()
                        .listForAllNamespaces(Templates.renderConfigMapRemoteConfigLabels());
                    if (existingRemoteConfigs.length > 0) {
                        const existingDeploymentsTable = remoteConfigsToDeploymentsTable(existingRemoteConfigs);
                        const promptOptions = {
                            default: false,
                            message: '⚠️ Warning: Existing solo deployment detected in cluster.\n\n' +
                                existingDeploymentsTable.join('\n') +
                                '\n\nCreating another deployment will require additional' +
                                ' CPU and memory resources. Do you want to proceed and create another deployment?',
                        };
                        const proceed = await task
                            .prompt(ListrInquirerPromptAdapter)
                            .run(confirmPrompt, promptOptions);
                        if (!proceed) {
                            throw new SoloError('Aborted by user');
                        }
                    }
                },
                skip: (context_) => context_.config.force === true || context_.config.quiet === true,
            },
            invokeSoloCommand(`solo ${ClusterReferenceCommandDefinition.CONNECT_COMMAND}`, ClusterReferenceCommandDefinition.CONNECT_COMMAND, () => {
                const argv = newArgv();
                argv.push(...ClusterReferenceCommandDefinition.CONNECT_COMMAND.split(' '), optionFromFlag(Flags.clusterRef), config.clusterRef, optionFromFlag(Flags.context), config.context);
                return argvPushGlobalFlags(argv);
            }, this.taskList),
            invokeSoloCommand(`solo ${DeploymentCommandDefinition.CREATE_COMMAND}`, DeploymentCommandDefinition.CREATE_COMMAND, () => {
                const argv = newArgv();
                argv.push(...DeploymentCommandDefinition.CREATE_COMMAND.split(' '), optionFromFlag(Flags.deployment), config.deployment, optionFromFlag(Flags.namespace), config.namespace.name);
                return argvPushGlobalFlags(argv);
            }, this.taskList),
            invokeSoloCommand(`solo ${DeploymentCommandDefinition.ATTACH_COMMAND}`, DeploymentCommandDefinition.ATTACH_COMMAND, () => {
                const argv = newArgv();
                argv.push(...DeploymentCommandDefinition.ATTACH_COMMAND.split(' '), optionFromFlag(Flags.deployment), config.deployment, optionFromFlag(Flags.clusterRef), config.clusterRef, optionFromFlag(Flags.numberOfConsensusNodes), config.numberOfConsensusNodes.toString());
                return argvPushGlobalFlags(argv);
            }, this.taskList),
            invokeSoloCommand(`solo ${ClusterReferenceCommandDefinition.SETUP_COMMAND}`, ClusterReferenceCommandDefinition.SETUP_COMMAND, () => {
                const argv = newArgv();
                argv.push(...ClusterReferenceCommandDefinition.SETUP_COMMAND.split(' '), optionFromFlag(Flags.clusterRef), config.clusterRef);
                return argvPushGlobalFlags(argv);
            }, this.taskList),
            invokeSoloCommand(`solo ${KeysCommandDefinition.KEYS_COMMAND}`, KeysCommandDefinition.KEYS_COMMAND, () => {
                const argv = newArgv();
                argv.push(...KeysCommandDefinition.KEYS_COMMAND.split(' '), optionFromFlag(Flags.deployment), config.deployment, optionFromFlag(Flags.generateGossipKeys), 'true', optionFromFlag(Flags.generateTlsKeys));
                return argvPushGlobalFlags(argv, config.cacheDir);
            }, this.taskList),
            {
                title: 'Create remote config components',
                task: async () => {
                    // Pre add remote config components to remote config
                    if (constants.ONE_SHOT_WITH_BLOCK_NODE === 'true') {
                        // Add Block Node
                        const blockNode = this.componentFactory.createNewBlockNodeComponent(config.clusterRef, config.namespace);
                        blockNode.metadata.phase = DeploymentPhase.REQUESTED;
                        this.remoteConfig.configuration.components.addNewComponent(blockNode, ComponentTypes.BlockNode, false, true);
                    }
                    // Add Explorer
                    if (config.deployExplorer) {
                        const explorer = this.componentFactory.createNewExplorerComponent(config.clusterRef, config.namespace);
                        explorer.metadata.phase = DeploymentPhase.REQUESTED;
                        this.remoteConfig.configuration.components.addNewComponent(explorer, ComponentTypes.Explorer, false, true);
                    }
                    // Add Mirror Node
                    if (config.deployMirrorNode) {
                        const mirrorNode = this.componentFactory.createNewMirrorNodeComponent(config.clusterRef, config.namespace);
                        mirrorNode.metadata.phase = DeploymentPhase.REQUESTED;
                        this.remoteConfig.configuration.components.addNewComponent(mirrorNode, ComponentTypes.MirrorNode, false, true);
                    }
                    // Add Relay
                    if (config.deployRelay) {
                        const nodeIds = [];
                        for (const alias of Templates.renderNodeAliasesFromCount(config.numberOfConsensusNodes, 0)) {
                            nodeIds.push(Templates.nodeIdFromNodeAlias(alias));
                        }
                        const relay = this.componentFactory.createNewRelayComponent(config.clusterRef, config.namespace, nodeIds);
                        relay.metadata.phase = DeploymentPhase.REQUESTED;
                        this.remoteConfig.configuration.components.addNewComponent(relay, ComponentTypes.RelayNodes, false, true);
                    }
                    await this.remoteConfig.persist();
                },
            },
            {
                title: 'Deploy Consensus Nodes',
                task: (_, task) => {
                    if (constants.ONE_SHOT_WITH_BLOCK_NODE.toLowerCase() !== 'true') {
                        task.title += ' and Block node';
                    }
                    return task.newListr([
                        invokeSoloCommand(`solo ${ConsensusCommandDefinition.DEPLOY_COMMAND}`, ConsensusCommandDefinition.DEPLOY_COMMAND, () => {
                            const argv = newArgv();
                            argv.push(...ConsensusCommandDefinition.DEPLOY_COMMAND.split(' '), optionFromFlag(Flags.deployment), config.deployment);
                            if (config.networkConfiguration) {
                                this.appendConfigToArgv(argv, config.networkConfiguration);
                            }
                            return argvPushGlobalFlags(argv, config.cacheDir);
                        }, this.taskList),
                        invokeSoloCommand(`solo ${BlockCommandDefinition.ADD_COMMAND}`, BlockCommandDefinition.ADD_COMMAND, () => {
                            const argv = newArgv();
                            argv.push(...BlockCommandDefinition.ADD_COMMAND.split(' '), optionFromFlag(Flags.deployment), config.deployment);
                            this.appendConfigToArgv(argv, config.blockNodeConfiguration);
                            return argvPushGlobalFlags(argv);
                        }, this.taskList, () => constants.ONE_SHOT_WITH_BLOCK_NODE.toLowerCase() !== 'true'),
                    ], { concurrent: config.parallelDeploy, rendererOptions: { collapseSubtasks: false } });
                },
            },
            {
                title: 'Deploy components and create accounts',
                task: async (_, task) => {
                    return task.newListr([
                        {
                            title: 'Setup and Start consensus node',
                            task: async (_, task) => {
                                return task.newListr([
                                    {
                                        title: 'Configure HikariCP connection pool limits',
                                        skip: () => !config.deployMirrorNode,
                                        task: () => {
                                            // Limit HikariCP idle connections. minimumIdle defaults to maximumPoolSize when unset,
                                            // causing every component to hold maximumPoolSize idle connections even under no load.
                                            config.mirrorNodeConfiguration ??= {};
                                            const existingValuesFile = config.mirrorNodeConfiguration['--values-file'];
                                            config.mirrorNodeConfiguration['--values-file'] = existingValuesFile
                                                ? `${existingValuesFile},${constants.MIRROR_NODE_HIKARI_LIMITS_FILE}`
                                                : constants.MIRROR_NODE_HIKARI_LIMITS_FILE;
                                        },
                                    },
                                    invokeSoloCommand(`solo ${ConsensusCommandDefinition.SETUP_COMMAND}`, ConsensusCommandDefinition.SETUP_COMMAND, () => {
                                        const argv = newArgv();
                                        argv.push(...ConsensusCommandDefinition.SETUP_COMMAND.split(' '), optionFromFlag(Flags.deployment), config.deployment);
                                        this.appendConfigToArgv(argv, config.setupConfiguration);
                                        return argvPushGlobalFlags(argv, config.cacheDir);
                                    }, this.taskList),
                                    invokeSoloCommand(`solo ${ConsensusCommandDefinition.START_COMMAND}`, ConsensusCommandDefinition.START_COMMAND, () => {
                                        const argv = newArgv();
                                        argv.push(...ConsensusCommandDefinition.START_COMMAND.split(' '), optionFromFlag(Flags.deployment), config.deployment);
                                        this.appendConfigToArgv(argv, config.consensusNodeConfiguration);
                                        return argvPushGlobalFlags(argv);
                                    }, this.taskList),
                                ], { concurrent: false, rendererOptions: { collapseSubtasks: false } });
                            },
                        },
                        {
                            title: '',
                            task: (_, task) => {
                                return task.newListr([
                                    {
                                        title: 'Deploy mirror node and extensions',
                                        skip: () => !config.deployMirrorNode,
                                        task: async (_, task) => {
                                            return task.newListr([
                                                invokeSoloCommand(`solo ${MirrorCommandDefinition.ADD_COMMAND}`, MirrorCommandDefinition.ADD_COMMAND, () => {
                                                    const argv = newArgv();
                                                    argv.push(...MirrorCommandDefinition.ADD_COMMAND.split(' '), optionFromFlag(Flags.deployment), config.deployment, optionFromFlag(Flags.clusterRef), config.clusterRef, optionFromFlag(Flags.pinger), optionFromFlag(Flags.enableIngress));
                                                    this.appendConfigToArgv(argv, config.mirrorNodeConfiguration);
                                                    return argvPushGlobalFlags(argv, config.cacheDir);
                                                }, this.taskList, () => !config.deployMirrorNode),
                                                {
                                                    title: 'Deploy Extensions',
                                                    skip: () => config.minimalSetup,
                                                    task: (_, task) => {
                                                        return task.newListr([
                                                            invokeSoloCommand(`solo ${ExplorerCommandDefinition.ADD_COMMAND}`, ExplorerCommandDefinition.ADD_COMMAND, () => {
                                                                const argv = newArgv();
                                                                argv.push(...ExplorerCommandDefinition.ADD_COMMAND.split(' '), optionFromFlag(Flags.deployment), config.deployment, optionFromFlag(Flags.clusterRef), config.clusterRef, optionFromFlag(Flags.explorerVersion), config.versions.explorer);
                                                                this.appendConfigToArgv(argv, {
                                                                    [optionFromFlag(Flags.mirrorNodeId)]: mirrorNodeId,
                                                                    [optionFromFlag(Flags.mirrorNamespace)]: config.namespace.name,
                                                                    ...config.explorerNodeConfiguration,
                                                                });
                                                                return argvPushGlobalFlags(argv, config.cacheDir);
                                                            }, this.taskList, () => !config.deployExplorer),
                                                            invokeSoloCommand(`solo ${RelayCommandDefinition.ADD_COMMAND}`, RelayCommandDefinition.ADD_COMMAND, () => {
                                                                const argv = newArgv();
                                                                argv.push(...RelayCommandDefinition.ADD_COMMAND.split(' '), optionFromFlag(Flags.deployment), config.deployment, optionFromFlag(Flags.clusterRef), config.clusterRef, optionFromFlag(Flags.nodeAliasesUnparsed), 'node1');
                                                                this.appendConfigToArgv(argv, {
                                                                    [optionFromFlag(Flags.mirrorNodeId)]: mirrorNodeId,
                                                                    [optionFromFlag(Flags.mirrorNamespace)]: config.namespace.name,
                                                                    ...config.relayNodeConfiguration,
                                                                });
                                                                return argvPushGlobalFlags(argv);
                                                            }, this.taskList, () => !config.deployRelay),
                                                        ], { concurrent: config.parallelDeploy, rendererOptions: { collapseSubtasks: false } });
                                                    },
                                                },
                                            ], { concurrent: false, rendererOptions: { collapseSubtasks: false } });
                                        },
                                    },
                                    // Pipeline B: create accounts (concurrent with Pipeline A)
                                    {
                                        title: 'Create Accounts',
                                        skip: () => config.predefinedAccounts === false,
                                        task: async (_, task) => {
                                            await this.localConfig.load();
                                            await this.remoteConfig.loadAndValidate(argv);
                                            const subTasks = [];
                                            const client = await this.accountManager.loadNodeClient(config.namespace, this.remoteConfig.getClusterRefs(), config.deployment);
                                            const realm = this.localConfig.configuration.realmForDeployment(config.deployment);
                                            const shard = this.localConfig.configuration.shardForDeployment(config.deployment);
                                            // Check if Topic with ID 1001 exists, if not create a buffer topic to bump the entity ID counter
                                            // so that created accounts have IDs start from x.x.1002
                                            try {
                                                const entity1001Query = new TopicInfoQuery().setTopicId(TopicId.fromString(entityId(realm, shard, 1001)));
                                                await entity1001Query.execute(client);
                                            }
                                            catch (error) {
                                                try {
                                                    if (error.message.includes('INVALID_TOPIC_ID')) {
                                                        const bufferTopic = new TopicCreateTransaction().setTopicMemo('Buffer topic to bump entity IDs');
                                                        await bufferTopic.execute(client);
                                                    }
                                                }
                                                catch (error) {
                                                    this.logger.warn('Failed to create topic. Created account IDs may be offset from the expected values.', error);
                                                }
                                            }
                                            const accountsToCreate = [...predefinedEcdsaAccountsWithAlias];
                                            for (const [index, account] of accountsToCreate.entries()) {
                                                // inject index to avoid closure issues
                                                ((index, account) => {
                                                    subTasks.push({
                                                        title: `Creating Account ${index}`,
                                                        task: async (context_, subTask) => {
                                                            await helpers.sleep(Duration.ofMillis(100 * index));
                                                            const createdAccount = await this.accountManager.createNewAccount(context_.config.namespace, account.privateKey, account.balance.to(HbarUnit.Hbar).toNumber(), account.alias, context_.config.context);
                                                            context_.createdAccounts.push({
                                                                accountId: AccountId.fromString(createdAccount.accountId),
                                                                data: account,
                                                                alias: createdAccount.accountAlias,
                                                                publicKey: createdAccount.publicKey,
                                                            });
                                                            subTask.title = `Account created: ${createdAccount.accountId.toString()}`;
                                                        },
                                                    });
                                                })(index, account);
                                            }
                                            return task.newListr(subTasks, {
                                                concurrent: true,
                                                rendererOptions: { collapseSubtasks: false },
                                            });
                                        },
                                    },
                                ], { concurrent: config.parallelDeploy, rendererOptions: { collapseSubtasks: false } });
                            },
                        },
                    ], { concurrent: false, rendererOptions: { collapseSubtasks: false } });
                },
            },
            {
                title: 'Finish',
                task: async (context_) => {
                    const outputDirectory = this.getOneShotOutputDirectory(context_.config.deployment);
                    this.logger.info(`Output directory: ${outputDirectory}`);
                    this.showOneShotUserNotes(context_, false, PathEx.join(outputDirectory, 'notes'));
                    this.showVersions(PathEx.join(outputDirectory, 'versions'), config);
                    this.showPortForwards(PathEx.join(outputDirectory, 'forwards'));
                    this.showAccounts(context_.createdAccounts, context_, PathEx.join(outputDirectory, 'accounts.json'));
                    this.cacheDeploymentName(context_, PathEx.join(constants.SOLO_CACHE_DIR, 'last-one-shot-deployment.txt'));
                    return;
                },
            },
        ], constants.LISTR_DEFAULT_OPTIONS.DEFAULT);
        try {
            await tasks.run();
        }
        catch (error) {
            await this.performRollback(error, config);
        }
        finally {
            this.oneShotState.deactivate();
            const cleanupPromises = [];
            if (oneShotLease) {
                cleanupPromises.push(oneShotLease.release(true).catch((error) => {
                    this.logger.error('Error releasing one-shot lease:', error);
                }));
            }
            cleanupPromises.push(this.taskList
                .callCloseFunctions()
                .then()
                .catch((error) => {
                this.logger.error('Error during closing task list:', error);
            }));
            await Promise.all(cleanupPromises);
        }
        return true;
    }
    showOneShotUserNotes(context_, isMultiple = false, outputFile) {
        const messageGroupKey = isMultiple ? 'one-shot-multiple-user-notes' : 'one-shot-user-notes';
        const title = isMultiple ? 'One Shot Multiple User Notes' : 'One Shot User Notes';
        this.logger.addMessageGroup(messageGroupKey, title);
        const data = [
            `Cluster Reference: ${context_.config.clusterRef}`,
            `Deployment Name: ${context_.config.deployment}`,
            `Namespace Name: ${context_.config.namespace.name}`,
        ];
        for (const line of data) {
            this.logger.addMessageGroupMessage(messageGroupKey, line);
        }
        if (isMultiple) {
            this.logger.addMessageGroupMessage(messageGroupKey, `Number of Consensus Nodes: ${context_.config.numberOfConsensusNodes}`);
        }
        this.logger.addMessageGroupMessage(messageGroupKey, 'To quickly delete the deployed resources, run the following command:\n' +
            `kubectl delete ns ${context_.config.namespace.name}`);
        this.logger.showMessageGroup(messageGroupKey);
        if (outputFile) {
            const fileData = data.join('\n') + '\n';
            createDirectoryIfNotExists(outputFile);
            fs.writeFileSync(outputFile, fileData);
            this.logger.showUser(chalk.green(`✅ User notes saved to file: ${outputFile}`));
        }
    }
    showVersions(outputFile, config) {
        const messageGroupKey = 'versions-used';
        this.logger.addMessageGroup(messageGroupKey, 'Versions Used');
        const data = [
            `Solo Chart Version: ${config.versions.soloChart}`,
            `Consensus Node Version: ${config.versions.consensus}`,
            `Mirror Node Version: ${config.versions.mirror}`,
            `Explorer Version: ${config.versions.explorer}`,
            `JSON RPC Relay Version: ${config.versions.relay}`,
        ];
        for (const line of data) {
            this.logger.addMessageGroupMessage(messageGroupKey, line);
        }
        this.logger.showMessageGroup(messageGroupKey);
        if (outputFile) {
            const fileData = data.join('\n') + '\n';
            createDirectoryIfNotExists(outputFile);
            fs.writeFileSync(outputFile, fileData);
            this.logger.showUser(chalk.green(`✅ Versions used saved to file: ${outputFile}`));
        }
    }
    cacheDeploymentName(context, outputFile) {
        fs.writeFileSync(outputFile, context.config.deployment);
        this.logger.showUser(chalk.green(`✅ Deployment name (${context.config.deployment}) saved to file: ${outputFile}`));
    }
    getOneShotOutputDirectory(deploymentName) {
        return PathEx.join(constants.SOLO_HOME_DIR, `one-shot-${deploymentName}`);
    }
    showAccounts(createdAccounts = [], context, outputFile) {
        if (createdAccounts.length > 0) {
            createdAccounts.sort((a, b) => a.accountId.compare(b.accountId));
            const ecdsaAccounts = createdAccounts.filter((account) => account.data.group === PREDEFINED_ACCOUNT_GROUPS.ECDSA);
            const aliasAccounts = createdAccounts.filter((account) => account.data.group === PREDEFINED_ACCOUNT_GROUPS.ECDSA_ALIAS);
            const ed25519Accounts = createdAccounts.filter((account) => account.data.group === PREDEFINED_ACCOUNT_GROUPS.ED25519);
            const systemAccountsGroupKey = 'system-accounts';
            const messageGroupKey = 'accounts-created';
            const ecdsaGroupKey = 'accounts-created-ecdsa';
            const ecdsaAliasGroupKey = 'accounts-created-ecdsa-alias';
            const ed25519GroupKey = 'accounts-created-ed25519';
            const realm = this.localConfig.configuration.realmForDeployment(context.config.deployment);
            const shard = this.localConfig.configuration.shardForDeployment(context.config.deployment);
            const operatorAccountData = {
                name: 'Operator',
                accountId: entityId(shard, realm, 2),
                publicKey: constants.GENESIS_PUBLIC_KEY,
            };
            if (constants.GENESIS_KEY === constants.DEFAULT_GENESIS_KEY) {
                operatorAccountData.privateKey = constants.DEFAULT_GENESIS_KEY;
            }
            const systemAccounts = [operatorAccountData];
            if (systemAccounts.length > 0) {
                this.logger.addMessageGroup(systemAccountsGroupKey, 'System Accounts');
                for (const account of systemAccounts) {
                    let message = `${account.name} Account ID: ${account.accountId.toString()}, Public Key: ${account.publicKey.toString()}`;
                    if (account.privateKey) {
                        message += `, Private Key: ${account.privateKey}`;
                    }
                    this.logger.addMessageGroupMessage(systemAccountsGroupKey, message);
                }
                this.logger.showMessageGroup(systemAccountsGroupKey);
            }
            this.logger.addMessageGroup(messageGroupKey, 'Created Accounts');
            this.logger.addMessageGroup(ecdsaGroupKey, 'ECDSA Accounts (Not EVM compatible, See ECDSA Alias Accounts above)');
            this.logger.addMessageGroup(ecdsaAliasGroupKey, 'ECDSA Alias Accounts (EVM compatible)');
            this.logger.addMessageGroup(ed25519GroupKey, 'ED25519 Accounts');
            if (aliasAccounts.length > 0) {
                for (const account of aliasAccounts) {
                    this.logger.addMessageGroupMessage(ecdsaAliasGroupKey, `Account ID: ${account.accountId.toString()}, Public address: ${account.alias}, Private Key: 0x${account.data.privateKey.toStringRaw()}, Balance: ${account.data.balance.toString()}`);
                }
                this.logger.showMessageGroup(ecdsaAliasGroupKey);
            }
            if (ed25519Accounts.length > 0) {
                for (const account of ed25519Accounts) {
                    this.logger.addMessageGroupMessage(ed25519GroupKey, `Account ID: ${account.accountId.toString()}, Private Key: 0x${account.data.privateKey.toStringRaw()}, Balance: ${account.data.balance.toString()}`);
                }
                this.logger.showMessageGroup(ed25519GroupKey);
            }
            if (ecdsaAccounts.length > 0) {
                for (const account of ecdsaAccounts) {
                    this.logger.addMessageGroupMessage(ecdsaGroupKey, `Account ID: ${account.accountId.toString()}, Private Key: 0x${account.data.privateKey.toStringRaw()}, Balance: ${account.data.balance.toString()}`);
                }
                this.logger.showMessageGroup(ecdsaGroupKey);
            }
            if (outputFile) {
                createDirectoryIfNotExists(outputFile);
                // Format account data in the same way as it appears in the console output
                const formattedCreatedAccounts = createdAccounts.map((account) => {
                    const formattedAccount = {
                        accountId: account.accountId.toString(),
                        privateKey: `0x${account.data.privateKey.toStringRaw()}`,
                        publicKey: `0x${PublicKey.fromString(account.publicKey).toStringRaw()}`,
                        balance: account.data.balance.toString(),
                        group: account.data.group,
                    };
                    // Add alias field for ECDSA_ALIAS accounts
                    if (account.data.group === PREDEFINED_ACCOUNT_GROUPS.ECDSA_ALIAS && account.alias) {
                        formattedAccount['publicAddress'] = account.alias;
                    }
                    return formattedAccount;
                });
                // Format system accounts data
                const formattedSystemAccounts = systemAccounts.map(account => ({
                    name: account.name,
                    accountId: account.accountId.toString(),
                    publicKey: account.publicKey.toString(),
                    privateKey: account.privateKey,
                }));
                // Create the structured output with both systemAccounts and createdAccounts
                const outputData = {
                    systemAccounts: formattedSystemAccounts,
                    createdAccounts: formattedCreatedAccounts,
                };
                fs.writeFileSync(outputFile, JSON.stringify(outputData, undefined, 2));
                this.logger.showUser(chalk.green(`✅ Created accounts saved to file in JSON format: ${outputFile}`));
            }
            this.logger.showUser('For more information on public and private keys see: https://docs.hedera.com/hedera/core-concepts/keys-and-signatures');
        }
    }
    showPortForwards(outputFile) {
        this.logger.showMessageGroup(constants.PORT_FORWARDING_MESSAGE_GROUP);
        if (outputFile) {
            const messages = this.logger.getMessageGroup(constants.PORT_FORWARDING_MESSAGE_GROUP);
            const fileData = messages.join('\n') + '\n';
            createDirectoryIfNotExists(outputFile);
            fs.writeFileSync(outputFile, fileData);
            this.logger.showUser(chalk.green(`✅ Port forwarding info saved to file: ${outputFile}`));
        }
    }
    async destroy(argv) {
        return this.destroyInternal(argv, DefaultOneShotCommand_1.DESTROY_FLAGS_LIST);
    }
    async destroyFalcon(argv) {
        return this.destroyInternal(argv, DefaultOneShotCommand_1.FALCON_DESTROY_FLAGS_LIST);
    }
    async destroyInternal(argv, flagsList) {
        let config;
        let remoteConfigLoaded = false;
        let oneShotLease;
        // don't make remote config call if deployment is not set or it will fail
        let hasExplorers = false;
        let hasRelays = false;
        const taskArray = [
            {
                title: 'Initialize',
                task: async (context_, task) => {
                    this.configManager.update(argv);
                    this.oneShotState.activate();
                    flags.disablePrompts(flagsList.optional);
                    const allFlags = [...flagsList.required, ...flagsList.optional];
                    await this.configManager.executePrompt(task, allFlags);
                    context_.config = this.configManager.getConfig(DefaultOneShotCommand_1.SINGLE_DESTROY_CONFIGS_NAME, allFlags);
                    config = context_.config;
                    await this.localConfig.load();
                    config.cacheDir ??= constants.SOLO_CACHE_DIR;
                    if (!config.deployment) {
                        const deployments = this.localConfig.configuration.deployments;
                        if (deployments.length === 0) {
                            this.logger.showUser('No deployments found in local config, have they already been deleted?');
                            config.skipAll = true;
                            return;
                        }
                        if (deployments.length > 1) {
                            const selectedDeployment = (await task.prompt(ListrInquirerPromptAdapter).run(selectPrompt, {
                                message: 'Select deployment to destroy',
                                choices: deployments.map((deployment) => {
                                    const clusterNames = (deployment.clusters ?? [])
                                        .map((cluster) => cluster?.toString())
                                        .filter(Boolean);
                                    return {
                                        name: `${deployment.name} (ns: ${deployment.namespace}, clusters: ${clusterNames || 'unknown'})`,
                                        value: deployment.name,
                                    };
                                }),
                            }));
                            if (!selectedDeployment) {
                                throw new SoloError('Deployment selection cannot be empty');
                            }
                            config.deployment = selectedDeployment;
                        }
                        else {
                            // Only one deployment exists, use it directly
                            const deployment = deployments.get(0);
                            if (!deployment || !deployment.name) {
                                throw new SoloError('Invalid deployment configuration: deployment name is missing');
                            }
                            config.deployment = deployment.name;
                        }
                        this.configManager.setFlag(flags.deployment, config.deployment);
                    }
                    const selectedDeployment = this.localConfig.configuration.deployments.find((deployment) => deployment.name === config.deployment);
                    if (selectedDeployment?.clusters?.length) {
                        const firstCluster = selectedDeployment.clusters?.find((cluster) => cluster !== null && cluster !== undefined);
                        if (firstCluster) {
                            config.clusterRef ??= firstCluster.toString();
                        }
                    }
                    config.clusterRef ??= this.localConfig.configuration.clusterRefs.keys().next().value;
                    config.context ??= this.localConfig.configuration.clusterRefs.get(config.clusterRef)?.toString();
                    remoteConfigLoaded = await this.loadRemoteConfigOrWarn(argv);
                    try {
                        config.namespace ??= await resolveNamespaceFromDeployment(this.localConfig, this.configManager, task);
                    }
                    catch (error) {
                        if (error.message?.includes('not found in local config')) {
                            this.logger.showUser(`Deployment: ${config.deployment}, not found in local config, has it already been deleted?`);
                            config.skipAll = true;
                            return;
                        }
                        else {
                            throw error;
                        }
                    }
                    try {
                        const kubeContextConnectionSuccessful = await this.k8Factory
                            .default()
                            .contexts()
                            .testContextConnection(config.context);
                        if (!kubeContextConnectionSuccessful) {
                            config.skipAll = true;
                            return;
                        }
                    }
                    catch (error) {
                        this.logger.error(`Error connecting to cluster with context ${config.context}:`, error);
                    }
                    try {
                        if (config.deployment && config.namespace && config.context) {
                            await this.remoteConfig.loadAndValidate(argv);
                            config.skipAll = false;
                        }
                        else {
                            config.skipAll = true;
                            return;
                        }
                    }
                    catch (error) {
                        if (error instanceof ResourceNotFoundError ||
                            error.cause instanceof ResourceNotFoundError ||
                            error instanceof NoKubeConfigContextError ||
                            error.cause instanceof NoKubeConfigContextError) {
                            this.logger.showUser('Remote config not found. This may indicate that the deployment has already been deleted or there is an issue with the cluster. Proceeding with best effort cleanup.');
                            this.logger.error('Error loading remote config:', error);
                            config.skipAll = true;
                            return;
                        }
                        else {
                            throw error;
                        }
                    }
                    hasExplorers = this.remoteConfig.configuration.components.state.explorers.length > 0;
                    hasRelays = this.remoteConfig.configuration.components.state.relayNodes.length > 0;
                },
            },
            {
                title: 'Acquire deployment lock',
                task: async (context_, task) => {
                    oneShotLease = await this.leaseManager.create();
                    return ListrLock.newAcquireLockTask(oneShotLease, task);
                },
                skip: () => config.skipAll,
            },
            {
                title: 'Destroy extended setup',
                task: async (context_, task) => {
                    const subTasks = [
                        invokeSoloCommand(`solo ${ExplorerCommandDefinition.DESTROY_COMMAND}`, ExplorerCommandDefinition.DESTROY_COMMAND, () => {
                            const argv = newArgv();
                            argv.push(...ExplorerCommandDefinition.DESTROY_COMMAND.split(' '), optionFromFlag(flags.clusterRef), config.clusterRef, optionFromFlag(flags.deployment), config.deployment, optionFromFlag(flags.quiet), optionFromFlag(flags.force));
                            return argvPushGlobalFlags(argv);
                        }, this.taskList, () => {
                            return !hasExplorers;
                        }),
                        invokeSoloCommand(`solo ${RelayCommandDefinition.DESTROY_COMMAND}`, RelayCommandDefinition.DESTROY_COMMAND, () => {
                            const argv = newArgv();
                            argv.push(...RelayCommandDefinition.DESTROY_COMMAND.split(' '), optionFromFlag(flags.clusterRef), config.clusterRef, optionFromFlag(flags.deployment), config.deployment, optionFromFlag(flags.nodeAliasesUnparsed), 'node1', optionFromFlag(flags.quiet));
                            return argvPushGlobalFlags(argv);
                        }, this.taskList, () => {
                            return !hasRelays;
                        }),
                    ];
                    // set up the sub-tasks
                    return task.newListr(subTasks, {
                        concurrent: true,
                        exitOnError: false,
                        rendererOptions: {
                            collapseSubtasks: false,
                        },
                    });
                },
                skip: () => {
                    if (config.skipAll || !config.deployment) {
                        return true;
                    }
                    return !hasExplorers && !hasRelays;
                },
            },
            invokeSoloCommand(`solo ${MirrorCommandDefinition.DESTROY_COMMAND}`, MirrorCommandDefinition.DESTROY_COMMAND, () => {
                const argv = newArgv();
                argv.push(...MirrorCommandDefinition.DESTROY_COMMAND.split(' '), optionFromFlag(flags.clusterRef), config.clusterRef, optionFromFlag(flags.deployment), config.deployment, optionFromFlag(flags.quiet), optionFromFlag(flags.force), optionFromFlag(flags.devMode));
                return argvPushGlobalFlags(argv);
            }, this.taskList, () => config.skipAll ||
                !config.deployment ||
                this.remoteConfig.configuration.components.state.mirrorNodes.length === 0),
            invokeSoloCommand(`solo ${BlockCommandDefinition.DESTROY_COMMAND}`, BlockCommandDefinition.DESTROY_COMMAND, () => {
                const argv = newArgv();
                argv.push(...BlockCommandDefinition.DESTROY_COMMAND.split(' '), optionFromFlag(Flags.deployment), config.deployment, optionFromFlag(flags.clusterRef), config.clusterRef, optionFromFlag(flags.quiet));
                return argvPushGlobalFlags(argv);
            }, this.taskList, () => config.skipAll ||
                !config.deployment ||
                constants.ONE_SHOT_WITH_BLOCK_NODE.toLowerCase() !== 'true' ||
                (remoteConfigLoaded && this.remoteConfig.configuration.components.state.blockNodes.length === 0)),
            invokeSoloCommand(`solo ${ConsensusCommandDefinition.DESTROY_COMMAND}`, ConsensusCommandDefinition.DESTROY_COMMAND, () => {
                const argv = newArgv();
                argv.push(...ConsensusCommandDefinition.DESTROY_COMMAND.split(' '), optionFromFlag(flags.deployment), config.deployment, optionFromFlag(flags.quiet), optionFromFlag(flags.force), optionFromFlag(flags.deletePvcs), optionFromFlag(flags.deleteSecrets), optionFromFlag(flags.enableTimeout));
                return argvPushGlobalFlags(argv);
            }, this.taskList, () => config.skipAll || !config.deployment),
            invokeSoloCommand(`solo ${ClusterReferenceCommandDefinition.RESET_COMMAND}`, ClusterReferenceCommandDefinition.RESET_COMMAND, () => {
                const argv = newArgv();
                argv.push(...ClusterReferenceCommandDefinition.RESET_COMMAND.split(' '), optionFromFlag(flags.clusterRef), config.clusterRef, optionFromFlag(flags.quiet), optionFromFlag(flags.force));
                return argvPushGlobalFlags(argv);
            }, this.taskList, () => config.skipAll || !config.deployment),
            invokeSoloCommand(`solo ${ClusterReferenceCommandDefinition.DISCONNECT_COMMAND}`, ClusterReferenceCommandDefinition.DISCONNECT_COMMAND, () => {
                const argv = newArgv();
                argv.push(...ClusterReferenceCommandDefinition.DISCONNECT_COMMAND.split(' '), optionFromFlag(flags.clusterRef), config.clusterRef, optionFromFlag(flags.quiet));
                return argvPushGlobalFlags(argv);
            }, this.taskList, () => config.skipAll || !config.deployment),
            invokeSoloCommand(`solo ${DeploymentCommandDefinition.DELETE_COMMAND}`, DeploymentCommandDefinition.DELETE_COMMAND, () => {
                const argv = newArgv();
                argv.push(...DeploymentCommandDefinition.DELETE_COMMAND.split(' '), optionFromFlag(flags.deployment), config.deployment, optionFromFlag(flags.quiet));
                return argvPushGlobalFlags(argv);
            }, this.taskList, () => !config.deployment),
            { title: 'Finish', task: async () => { } },
        ];
        const tasks = this.taskList.newOneShotSingleDestroyTaskList(taskArray, constants.LISTR_DEFAULT_OPTIONS.DEFAULT);
        try {
            await tasks.run();
        }
        catch (error) {
            throw new SoloError(`Error destroying Solo in one-shot mode: ${error.message}`, error);
        }
        finally {
            this.oneShotState.deactivate();
            const cleanupPromises = [];
            if (oneShotLease) {
                cleanupPromises.push(oneShotLease.release(true).catch((error) => {
                    this.logger.error('Error releasing one-shot lease:', error);
                }));
            }
            cleanupPromises.push(this.taskList
                .callCloseFunctions()
                .then()
                .catch((error) => this.logger.error('Error during closing task list:', error)));
            await Promise.all(cleanupPromises);
        }
        return true;
    }
    async info(_argv) {
        const tasks = new Listr([
            {
                title: 'Check for cached deployment',
                task: async (context_) => {
                    const deploymentFromFlag = this.configManager.getFlag(flags.deployment);
                    if (deploymentFromFlag) {
                        context_.deploymentName = deploymentFromFlag;
                        this.logger.showUser(chalk.cyan(`\nDeployment Name: ${chalk.bold(deploymentFromFlag)} (from flag)`));
                        return;
                    }
                    const cacheFile = PathEx.join(constants.SOLO_CACHE_DIR, 'last-one-shot-deployment.txt');
                    if (fs.existsSync(cacheFile)) {
                        const deploymentName = fs.readFileSync(cacheFile, 'utf8').trim();
                        if (deploymentName) {
                            context_.deploymentName = deploymentName;
                            this.logger.showUser(chalk.cyan(`\nDeployment Name: ${chalk.bold(deploymentName)} (from cache)`));
                            return;
                        }
                    }
                    await this.localConfig.load();
                    const deployments = this.localConfig.configuration.deployments;
                    if (deployments.length === 1) {
                        context_.deploymentName = deployments.get(0).name;
                        this.logger.showUser(chalk.cyan(`\nDeployment Name: ${chalk.bold(context_.deploymentName)} (single local deployment)`));
                        return;
                    }
                    if (deployments.length > 1) {
                        const deploymentNames = deployments.map((d) => d.name).join(', ');
                        throw new SoloError('No cached deployment found and multiple local deployments exist.\n' +
                            `Please specify ${optionFromFlag(flags.deployment)}.\n` +
                            `Available deployments: ${deploymentNames}`);
                    }
                    throw new SoloError('No cached deployment found. Please run a one-shot deployment first or pass ' +
                        `${optionFromFlag(flags.deployment)}.\n` +
                        `Expected cache file: ${cacheFile}`);
                },
            },
            {
                title: 'Load local configuration',
                task: async (context_) => {
                    await this.localConfig.load();
                    const deployment = this.localConfig.configuration.deployments.find((d) => d.name === context_.deploymentName);
                    if (!deployment) {
                        this.logger.showUser(chalk.yellow(`\n⚠️  Deployment '${context_.deploymentName}' not found in local configuration.\n` +
                            'This may be a deployment that was created but not properly registered.'));
                        return;
                    }
                    context_.deployment = deployment;
                    this.logger.showUser(chalk.cyan(`\nNamespace: ${chalk.bold(deployment.namespace)}`));
                    if (deployment.clusters && deployment.clusters.length > 0) {
                        const clusterNames = deployment.clusters.map((c) => c.toString()).join(', ');
                        this.logger.showUser(chalk.cyan(`Clusters: ${chalk.bold(clusterNames)}`));
                    }
                },
            },
            {
                title: 'Check cluster connectivity',
                task: async (context_, task) => {
                    if (!context_.deployment) {
                        task.skip('No deployment configuration found');
                        return;
                    }
                    const deployment = context_.deployment;
                    if (!deployment.clusters || deployment.clusters.length === 0) {
                        this.logger.showUser(chalk.yellow('\n⚠️  No clusters attached to this deployment.'));
                        return;
                    }
                    const clusterReference = deployment.clusters.get(0).toString();
                    const clusterContext = this.localConfig.configuration.clusterRefs.get(clusterReference);
                    if (!clusterContext) {
                        this.logger.showUser(chalk.yellow(`\n⚠️  Cluster reference '${clusterReference}' not found in configuration.`));
                        return;
                    }
                    try {
                        this.k8Factory.default().contexts().updateCurrent(clusterContext.toString());
                        const namespaces = await this.k8Factory.default().namespaces().list();
                        const targetNamespace = namespaces.find((ns) => ns.name === deployment.namespace);
                        if (!targetNamespace) {
                            this.logger.showUser(chalk.yellow(`\n⚠️  Namespace '${deployment.namespace}' not found in cluster '${clusterReference}'.` +
                                '\nThe deployment may have been destroyed or is not accessible.'));
                            return;
                        }
                        context_.clusterConnected = true;
                    }
                    catch (error) {
                        this.logger.showUser(chalk.yellow(`\n⚠️  Unable to connect to cluster '${clusterReference}'.\n` + `Error: ${error.message}`));
                    }
                },
            },
            {
                title: 'Fetch deployment state',
                task: async (context_, task) => {
                    if (!context_.clusterConnected || !context_.deployment) {
                        task.skip('Cluster not accessible or no deployment configuration');
                        return;
                    }
                    const deployment = context_.deployment;
                    try {
                        const namespaceName = NamespaceName.of(deployment.namespace);
                        const configMaps = await this.k8Factory.default().configMaps().list(namespaceName, []);
                        const remoteConfigMap = configMaps.find((cm) => cm.name === constants.SOLO_REMOTE_CONFIGMAP_NAME);
                        if (!remoteConfigMap) {
                            this.logger.showUser(chalk.yellow(`\n⚠️  Remote configuration not found in namespace '${deployment.namespace}'.` +
                                '\nThe deployment may have been partially destroyed.'));
                            return;
                        }
                        context_.remoteConfig = yaml.parse(remoteConfigMap.data[constants.SOLO_REMOTE_CONFIGMAP_DATA_KEY]);
                    }
                    catch (error) {
                        this.logger.showUser(chalk.yellow(`\n⚠️  Unable to fetch remote configuration: ${error.message}`));
                    }
                },
            },
            {
                title: 'Display deployment information',
                task: async (context_) => {
                    this.logger.showUser(chalk.cyan('\n=== Deployment Components ==='));
                    const versions = context_.remoteConfig.versions;
                    // Show versions
                    this.logger.showUser(chalk.cyan('\nVersions:'));
                    this.logger.showUser(`  Solo Chart Version: ${chalk.bold()}`);
                    this.logger.showUser(`  Consensus Node Version: ${chalk.bold(versions.consensusNode?.toString())}`);
                    this.logger.showUser(`  Mirror Node Version: ${chalk.bold(versions.mirrorNodeChart?.toString())}`);
                    this.logger.showUser(`  Explorer Version: ${chalk.bold(versions.explorerChart?.toString())}`);
                    this.logger.showUser(`  JSON RPC Relay Version: ${chalk.bold(versions.jsonRpcRelayChart?.toString())}`);
                    this.logger.showUser(`  Block Node Version: ${chalk.bold(versions.blockNodeChart?.toString())}`);
                    if (context_.remoteConfig) {
                        const components = context_.remoteConfig.state;
                        if (components) {
                            this.logger.showUser(chalk.cyan('\nDeployed Components:'));
                            if (components.consensusNodes && components.consensusNodes.length > 0) {
                                const nodeNames = components.consensusNodes
                                    .map((n) => Templates.renderNodeAliasFromNumber(n.metadata.id))
                                    .join(', ');
                                this.logger.showUser(`  ${chalk.green('✓')} Consensus Nodes: ${chalk.bold(components.consensusNodes.length)} (${nodeNames})`);
                            }
                            if (components.mirrorNodes && components.mirrorNodes.length > 0) {
                                this.logger.showUser(`  ${chalk.green('✓')} Mirror Nodes: ${chalk.bold(components.mirrorNodes.length)}`);
                            }
                            if (components.blockNodes && components.blockNodes.length > 0) {
                                this.logger.showUser(`  ${chalk.green('✓')} Block Nodes: ${chalk.bold(components.blockNodes.length)}`);
                            }
                            if (components.relayNodes && components.relayNodes.length > 0) {
                                this.logger.showUser(`  ${chalk.green('✓')} Relay Nodes: ${chalk.bold(components.relayNodes.length)}`);
                            }
                            if (components.explorers && components.explorers.length > 0) {
                                this.logger.showUser(`  ${chalk.green('✓')} Explorers: ${chalk.bold(components.explorers.length)}`);
                            }
                            if (components.postgres && components.postgres.length > 0) {
                                this.logger.showUser(`  ${chalk.green('✓')} Postgres: ${chalk.bold(components.postgres.length)}`);
                            }
                            if (components.redis && components.redis.length > 0) {
                                this.logger.showUser(`  ${chalk.green('✓')} Redis: ${chalk.bold(components.redis.length)}`);
                            }
                        }
                    }
                    else {
                        this.logger.showUser(chalk.yellow('\n⚠️  Remote configuration not available. Cannot display deployed components.'));
                    }
                    // Show information about where files are stored
                    const outputDirectory = this.getOneShotOutputDirectory(context_.deploymentName);
                    this.logger.showUser(chalk.cyan('\n=== Deployment Files ==='));
                    if (fs.existsSync(outputDirectory)) {
                        this.logger.showUser(`Output directory: ${chalk.bold(outputDirectory)}`);
                        const notesFile = PathEx.join(outputDirectory, 'notes');
                        const versionsFile = PathEx.join(outputDirectory, 'versions');
                        const forwardsFile = PathEx.join(outputDirectory, 'forwards');
                        const accountsFile = PathEx.join(outputDirectory, 'accounts.json');
                        if (fs.existsSync(notesFile)) {
                            this.logger.showUser(`  ${chalk.green('✓')} Notes: ${notesFile}`);
                        }
                        if (fs.existsSync(versionsFile)) {
                            this.logger.showUser(`  ${chalk.green('✓')} Versions: ${versionsFile}`);
                        }
                        if (fs.existsSync(forwardsFile)) {
                            this.logger.showUser(`  ${chalk.green('✓')} Port forwards: ${forwardsFile}`);
                        }
                        if (fs.existsSync(accountsFile)) {
                            this.logger.showUser(`  ${chalk.green('✓')} Accounts: ${accountsFile}`);
                        }
                    }
                    else {
                        this.logger.showUser(chalk.yellow(`\n⚠️  Output directory not found: ${outputDirectory}`));
                    }
                    this.logger.showUser(chalk.green('\n✓ Deployment information retrieved successfully.\n'));
                },
            },
        ], constants.LISTR_DEFAULT_OPTIONS.DEFAULT);
        try {
            await tasks.run();
        }
        catch (error) {
            throw new SoloError(`Error retrieving deployment information: ${error.message}`, error);
        }
        return true;
    }
    async close() { } // no-op
    resolveOneShotComponentVersions(useEdge) {
        return useEdge
            ? {
                soloChart: version.SOLO_CHART_EDGE_VERSION,
                consensus: version.HEDERA_PLATFORM_EDGE_VERSION,
                mirror: version.MIRROR_NODE_EDGE_VERSION,
                explorer: version.EXPLORER_EDGE_VERSION,
                relay: version.HEDERA_JSON_RPC_RELAY_EDGE_VERSION,
                blockNode: version.BLOCK_NODE_EDGE_VERSION,
            }
            : {
                soloChart: version.SOLO_CHART_VERSION,
                consensus: version.HEDERA_PLATFORM_VERSION,
                mirror: version.MIRROR_NODE_VERSION,
                explorer: version.EXPLORER_VERSION,
                relay: version.HEDERA_JSON_RPC_RELAY_VERSION,
                blockNode: version.BLOCK_NODE_VERSION,
            };
    }
};
DefaultOneShotCommand = DefaultOneShotCommand_1 = __decorate([
    injectable(),
    __param(0, inject(InjectTokens.AccountManager)),
    __param(1, inject(InjectTokens.SharedResourceManager)),
    __metadata("design:paramtypes", [Function, SharedResourceManager])
], DefaultOneShotCommand);
export { DefaultOneShotCommand };
//# sourceMappingURL=default-one-shot.js.map