// SPDX-License-Identifier: Apache-2.0
import { BaseCommandTest } from './base-command-test.js';
import { main } from '../../../../src/index.js';
import { InjectTokens } from '../../../../src/core/dependency-injection/inject-tokens.js';
import { Duration } from '../../../../src/core/time/duration.js';
import { container } from 'tsyringe-neo';
import { expect } from 'chai';
import { Flags as flags, Flags } from '../../../../src/commands/flags.js';
import { ConsensusCommandDefinition } from '../../../../src/commands/command-definitions/consensus-command-definition.js';
import { it } from 'mocha';
import { sleep } from '../../../../src/core/helpers.js';
import * as constants from '../../../../src/core/constants.js';
export class NetworkTest extends BaseCommandTest {
    static soloNetworkDeployArgv(testName, deployment, enableLocalBuildPathTesting, localBuildReleaseTag, loadBalancerEnabled) {
        const { newArgv, argvPushGlobalFlags, optionFromFlag } = NetworkTest;
        const argv = newArgv();
        argv.push(ConsensusCommandDefinition.COMMAND_NAME, ConsensusCommandDefinition.NETWORK_SUBCOMMAND_NAME, ConsensusCommandDefinition.NETWORK_DEPLOY, optionFromFlag(Flags.deployment), deployment, optionFromFlag(flags.persistentVolumeClaims), optionFromFlag(Flags.serviceMonitor), optionFromFlag(Flags.podLog));
        // have to enable load balancer to resolve cross cluster in multi-cluster
        if (loadBalancerEnabled) {
            argv.push(optionFromFlag(Flags.loadBalancerEnabled));
        }
        if (enableLocalBuildPathTesting) {
            argv.push(optionFromFlag(Flags.releaseTag), localBuildReleaseTag);
        }
        argvPushGlobalFlags(argv, testName, true, true);
        return argv;
    }
    static deploy(options) {
        const { testName, deployment, namespace, contexts, enableLocalBuildPathTesting, localBuildReleaseTag, loadBalancerEnabled, clusterReferenceNameArray, consensusNodesCount, } = options;
        const { soloNetworkDeployArgv } = NetworkTest;
        it(`${testName}: consensus network deploy`, async () => {
            await main(soloNetworkDeployArgv(testName, deployment, enableLocalBuildPathTesting, localBuildReleaseTag, loadBalancerEnabled));
            const k8Factory = container.resolve(InjectTokens.K8Factory);
            const clusterCount = clusterReferenceNameArray.length;
            const base = Math.floor(consensusNodesCount / clusterCount);
            const remainder = consensusNodesCount % clusterCount;
            const nodeCountsPerCluster = clusterReferenceNameArray.map((_, index) => index < remainder ? base + 1 : base);
            for (const [index, context_] of contexts.entries()) {
                const nodeCount = nodeCountsPerCluster[index];
                const namespaceExists = await k8Factory.getK8(context_).namespaces().has(namespace);
                expect(namespaceExists, `namespace ${namespace} should exist in ${context_}`).to.be.true;
                const pods = await k8Factory
                    .getK8(context_)
                    .pods()
                    .list(namespace, ['solo.hedera.com/type=network-node']);
                expect(pods.length, `expected exactly ${nodeCount} network-node pod in namespace ${namespace} for context ${context_}`).to.equal(nodeCount);
            }
        }).timeout(Duration.ofMinutes(5).toMillis());
    }
    static soloNetworkDestroyArgv(testName, deployment) {
        const { newArgv, argvPushGlobalFlags, optionFromFlag } = NetworkTest;
        const argv = newArgv();
        argv.push(ConsensusCommandDefinition.COMMAND_NAME, ConsensusCommandDefinition.NETWORK_SUBCOMMAND_NAME, ConsensusCommandDefinition.NETWORK_DESTROY, optionFromFlag(Flags.deployment), deployment, optionFromFlag(Flags.deletePvcs), optionFromFlag(Flags.deleteSecrets), optionFromFlag(Flags.force), optionFromFlag(Flags.quiet));
        argvPushGlobalFlags(argv, testName, false, true);
        return argv;
    }
    static destroy(options) {
        const { testName, deployment } = options;
        const { soloNetworkDestroyArgv } = NetworkTest;
        it(`${testName}: consensus network destroy`, async () => {
            await main(soloNetworkDestroyArgv(testName, deployment));
        }).timeout(Duration.ofMinutes(10).toMillis());
        it(`${testName}: consensus network destroy should success`, async () => {
            const { namespace, contexts: contextRecord, testLogger: logger } = options;
            const k8Factory = container.resolve(InjectTokens.K8Factory);
            const chartManager = container.resolve(InjectTokens.ChartManager);
            const contexts = [...contextRecord.values()]; // get all contexts
            async function getPodsCountInMultipleNamespaces(label) {
                return await Promise.all(contexts.map((context) => k8Factory.getK8(context).pods().list(namespace, label))).then((results) => results.flat().length);
            }
            async function waitUntilPodsGone(label) {
                logger.showUser(`Waiting for pod ${label} to be gone`);
                while (true) {
                    const podsCount = await getPodsCountInMultipleNamespaces(label);
                    if (podsCount === 0) {
                        break;
                    }
                    await sleep(Duration.ofSeconds(3));
                }
            }
            await waitUntilPodsGone(['solo.hedera.com/type=network-node']);
            await waitUntilPodsGone(['app=minio']);
            const isChartInstalled = await chartManager.isChartInstalled(namespace, constants.SOLO_DEPLOYMENT_CHART);
            expect(isChartInstalled).to.be.false;
            await expect(k8Factory.getK8(contexts[0]).pvcs().list(namespace, []), 'PVCs should be deleted in cluster[0]').eventually.to.have.lengthOf(0);
            await expect(k8Factory.getK8(contexts[1]).pvcs().list(namespace, []), 'PVCs should be deleted in cluster[1]').eventually.to.have.lengthOf(0);
            await expect(k8Factory.getK8(contexts[0]).secrets().list(namespace), 'Secrets should be deleted in cluster[0]').eventually.to.have.lengthOf(0);
            await expect(k8Factory.getK8(contexts[1]).secrets().list(namespace), 'Secrets should be deleted in cluster[1]').eventually.to.have.lengthOf(0);
        }).timeout(Duration.ofMinutes(2).toMillis());
    }
}
//# sourceMappingURL=network-test.js.map