// SPDX-License-Identifier: Apache-2.0
import sinon from 'sinon';
import { after, afterEach, before, beforeEach, describe, it } from 'mocha';
import { expect } from 'chai';
import { getTestCacheDirectory } from '../../test-utility.js';
import * as constants from '../../../src/core/constants.js';
import { sleep } from '../../../src/core/helpers.js';
import { Duration } from '../../../src/core/time/duration.js';
import * as fs from 'node:fs';
import * as yaml from 'yaml';
import { PathEx } from '../../../src/business/utils/path-ex.js';
import { SoloPinoLogger } from '../../../src/core/logging/solo-pino-logger.js';
import { container } from 'tsyringe-neo';
import { ClusterCommandTasks } from '../../../src/commands/cluster/tasks.js';
import { InjectTokens } from '../../../src/core/dependency-injection/inject-tokens.js';
import { EndToEndTestSuiteBuilder } from '../end-to-end-test-suite-builder.js';
import { ClusterReferenceTest } from './tests/cluster-reference-test.js';
import { main } from '../../../src/index.js';
const testName = 'cluster-test';
new EndToEndTestSuiteBuilder()
    .withTestName(testName)
    .withTestSuiteName('Dual Cluster Full E2E Test Suite')
    .withNamespace(testName)
    .withDeployment(`${testName}-deployment`)
    .withClusterCount(1)
    .withConsensusNodesCount(1)
    .withLoadBalancerEnabled(true)
    .withPinger(true)
    .withRealm(2)
    .withShard(3)
    .withServiceMonitor(true)
    .withPodLog(true)
    .withTestSuiteCallback((options) => {
    describe('Cluster E2E Test', () => {
        const { clusterReferenceNameArray, contexts, namespace } = options;
        const clusterReferenceName = clusterReferenceNameArray[0];
        const contextName = contexts[0];
        const clusterCmdTasks = container.resolve(ClusterCommandTasks);
        const chartManager = container.resolve(InjectTokens.ChartManager);
        const configManager = container.resolve(InjectTokens.ConfigManager);
        const k8Factory = container.resolve(InjectTokens.K8Factory);
        beforeEach(() => configManager.reset());
        // mock showUser and showJSON to silent logging during tests
        before(async () => {
            sinon.stub(SoloPinoLogger.prototype, 'showUser');
            sinon.stub(SoloPinoLogger.prototype, 'showJSON');
            await container.resolve(InjectTokens.LocalConfigRuntimeState).load();
        });
        after(async function () {
            // @ts-expect-error: TS2339 - to restore
            SoloPinoLogger.prototype.showUser.restore();
            // @ts-expect-error: TS2339 - to restore
            SoloPinoLogger.prototype.showJSON.restore();
            this.timeout(Duration.ofMinutes(3).toMillis());
            await k8Factory.default().namespaces().delete(namespace);
            ClusterReferenceTest.setup(options);
            do {
                await sleep(Duration.ofSeconds(5));
            } while (!(await chartManager.isChartInstalled(constants.SOLO_SETUP_NAMESPACE, constants.MINIO_OPERATOR_RELEASE_NAME)));
        });
        // give a few ticks so that connections can close
        afterEach(async () => await sleep(Duration.ofMillis(20)));
        it('should cleanup existing deployment', async () => {
            if (await chartManager.isChartInstalled(constants.SOLO_SETUP_NAMESPACE, constants.MINIO_OPERATOR_RELEASE_NAME)) {
                ClusterReferenceTest.reset(options);
            }
        }).timeout(Duration.ofMinutes(1).toMillis());
        it('solo cluster setup should fail with invalid cluster name', async () => {
            await expect(main(ClusterReferenceTest.soloClusterReferenceSetup(testName, clusterReferenceName, 'INVALID'))).to.be.rejectedWith("Namespace name 'INVALID' is invalid");
        }).timeout(Duration.ofMinutes(1).toMillis());
        it('solo cluster setup should work with valid args', async () => {
            await main(ClusterReferenceTest.soloClusterReferenceSetup(testName, clusterReferenceName));
        }).timeout(Duration.ofMinutes(1).toMillis());
        it('cluster-ref config connect should pass with correct data', async () => {
            const localConfigPath = PathEx.join(getTestCacheDirectory(), constants.DEFAULT_LOCAL_CONFIG_FILE);
            await main(ClusterReferenceTest.soloClusterReferenceConnectArgv(testName, clusterReferenceName, contextName));
            const localConfigYaml = fs.readFileSync(localConfigPath).toString();
            const localConfigData = yaml.parse(localConfigYaml);
            expect(localConfigData.clusterRefs).to.have.own.property(clusterReferenceName);
            expect(localConfigData.clusterRefs[clusterReferenceName]).to.equal(contextName);
        });
        it('solo cluster info should work', () => {
            ClusterReferenceTest.info(options);
        }).timeout(Duration.ofMinutes(1).toMillis());
        it('solo cluster list', async () => {
            ClusterReferenceTest.list(options);
        }).timeout(Duration.ofMinutes(1).toMillis());
        it('function showInstalledChartList should return right true', async () => {
            // @ts-expect-error to access private property
            await expect(clusterCmdTasks.showInstalledChartList()).to.eventually.be.undefined;
        }).timeout(Duration.ofMinutes(1).toMillis());
        // helm list would return an empty list if given invalid namespace
        it('solo cluster reset should fail with invalid cluster name', async () => {
            try {
                await main(ClusterReferenceTest.soloClusterReferenceReset(testName, 'INVALID'));
                expect.fail();
            }
            catch (error) {
                expect(error.message).to.include('Error on cluster reset');
            }
        }).timeout(Duration.ofMinutes(1).toMillis());
        it('solo cluster reset should work with valid args', async () => {
            ClusterReferenceTest.reset(options);
        }).timeout(Duration.ofMinutes(1).toMillis());
        it('cluster-ref config connect should fail with invalid context name', async () => {
            const invalidContextName = 'INVALID_CONTEXT';
            try {
                await main(ClusterReferenceTest.soloClusterReferenceConnectArgv(testName, clusterReferenceName, invalidContextName));
                expect.fail();
            }
            catch (error) {
                expect(error.message).to.include(`Context ${invalidContextName} is not valid for cluster`);
            }
        });
    });
})
    .build()
    .runTestSuite();
//# sourceMappingURL=cluster.test.js.map