// SPDX-License-Identifier: Apache-2.0
import { describe } from 'mocha';
import { resetForTest } from '../../test-container.js';
import { container } from 'tsyringe-neo';
import { InjectTokens } from '../../../src/core/dependency-injection/inject-tokens.js';
import fs from 'node:fs';
import { DEFAULT_LOCAL_CONFIG_FILE } from '../../../src/core/constants.js';
import { Duration } from '../../../src/core/time/duration.js';
import { PathEx } from '../../../src/business/utils/path-ex.js';
import { Client, AccountId, PrivateKey, Hbar, TransferTransaction, } from '@hiero-ledger/sdk';
import { EndToEndTestSuiteBuilder } from '../end-to-end-test-suite-builder.js';
import { main } from '../../../src/index.js';
import { BaseCommandTest } from './tests/base-command-test.js';
import { OneShotCommandDefinition } from '../../../src/commands/command-definitions/one-shot-command-definition.js';
import { MetricsServerImpl } from '../../../src/business/runtime-state/services/metrics-server-impl.js';
import * as constants from '../../../src/core/constants.js';
import { Flags } from '../../../src/commands/flags.js';
import { ShellRunner } from '../../../src/core/shell-runner.js';
const minimalSetup = process.env.SOLO_ONE_SHOT_MINIMAL_SETUP?.toLowerCase() === 'true';
const testName = minimalSetup ? 'one-shot-single-minimal' : 'one-shot-single';
const testTitle = 'One Shot Single E2E Test';
const endToEndTestSuite = new EndToEndTestSuiteBuilder()
    .withTestName(testName)
    .withTestSuiteName(`${testTitle} Suite`)
    .withNamespace(testName)
    .withDeployment(`${testName}-deployment`)
    .withClusterCount(1)
    .withMinimalSetup(process.env.SOLO_ONE_SHOT_MINIMAL_SETUP?.toLowerCase() === 'true')
    .withTestSuiteCallback((options) => {
    describe(testTitle, () => {
        const { testCacheDirectory, testLogger, namespace, contexts, deployment } = options;
        // TODO the kube config context causes issues if it isn't one of the selected clusters we are deploying to
        before(async () => {
            fs.rmSync(testCacheDirectory, { recursive: true, force: true });
            try {
                fs.rmSync(PathEx.joinWithRealPath(testCacheDirectory, '..', DEFAULT_LOCAL_CONFIG_FILE), {
                    force: true,
                });
            }
            catch {
                // allowed to fail if the file doesn't exist
            }
            if (!fs.existsSync(testCacheDirectory)) {
                fs.mkdirSync(testCacheDirectory, { recursive: true });
            }
            resetForTest(namespace.name, testCacheDirectory, false);
            for (const item of contexts) {
                const k8Client = container.resolve(InjectTokens.K8Factory).getK8(item);
                await k8Client.namespaces().delete(namespace);
            }
            testLogger.info(`${testName}: starting ${testName} e2e test`);
        }).timeout(Duration.ofMinutes(5).toMillis());
        after(async () => {
            await main(soloDeploymentDiagnosticsLogs(testName, deployment));
            testLogger.info(`${testName}: beginning ${testName}: destroy`);
            await main(soloOneShotDestroy(testName));
            testLogger.info(`${testName}: finished ${testName}: destroy`);
        }).timeout(Duration.ofMinutes(5).toMillis());
        // TODO pass in namespace for cache directory for proper destroy on restart
        it(`${testName}: deploy`, async () => {
            testLogger.info(`${testName}: beginning ${testName}: deploy`);
            await main(soloOneShotDeploy(testName, deployment, options.minimalSetup));
            testLogger.info(`${testName}: finished ${testName}: deploy`);
        }).timeout(Duration.ofMinutes(20).toMillis());
        it('Should perform a simple TransferTransaction', async () => {
            // These should be set in your environment or test config
            const operatorId = AccountId.fromString('0.0.2');
            const operatorKey = PrivateKey.fromStringED25519(constants.GENESIS_KEY);
            const recipientId = AccountId.fromString('0.0.3');
            const client = Client.forNetwork({ 'localhost:50211': '0.0.3' }).setOperator(operatorId, operatorKey);
            const tx = await new TransferTransaction()
                .addHbarTransfer(operatorId, new Hbar(-1))
                .addHbarTransfer(recipientId, new Hbar(1))
                .execute(client);
            const receipt = await tx.getReceipt(client);
            if (receipt.status.toString() !== 'SUCCESS') {
                throw new Error(`TransferTransaction failed: ${receipt.status}`);
            }
        });
        it('Should write log metrics', async () => {
            if (minimalSetup) {
                try {
                    await new ShellRunner().run('helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/', [], true, false);
                    await new ShellRunner().run('helm repo add metallb https://metallb.github.io/metallb', [], true, false);
                    await new ShellRunner().run('helm upgrade --install metrics-server metrics-server/metrics-server --namespace kube-system --set "args[0]=--kubelet-insecure-tls"', [], true, false);
                    await new ShellRunner().run('helm upgrade --install metallb metallb/metallb --namespace metallb-system --create-namespace --atomic --wait --set speaker.frr.enabled=true', [], true, false);
                }
                catch (error) {
                    throw new Error(`${testName}: failed to install metrics-server or metallb in minimal setup: ${error.message}`);
                }
            }
            await new MetricsServerImpl().logMetrics(testName, PathEx.join(constants.SOLO_LOGS_DIR, `${testName}`));
        }).timeout(Duration.ofMinutes(60).toMillis());
        // TODO add verifications
    });
})
    .build();
endToEndTestSuite.runTestSuite();
export function soloOneShotDeploy(testName, deployment, minimalSetup) {
    const { newArgv, argvPushGlobalFlags, optionFromFlag } = BaseCommandTest;
    const argv = newArgv();
    argv.push(OneShotCommandDefinition.COMMAND_NAME, OneShotCommandDefinition.SINGLE_SUBCOMMAND_NAME, OneShotCommandDefinition.SINGLE_DEPLOY, optionFromFlag(Flags.deployment), deployment, optionFromFlag(Flags.minimalSetup), minimalSetup ? 'true' : 'false');
    argvPushGlobalFlags(argv, testName);
    return argv;
}
export function soloOneShotDestroy(testName) {
    const { newArgv, argvPushGlobalFlags } = BaseCommandTest;
    const argv = newArgv();
    argv.push('one-shot', 'single', 'destroy');
    argvPushGlobalFlags(argv, testName);
    return argv;
}
export function soloDeploymentDiagnosticsLogs(testName, deployment) {
    const { newArgv, argvPushGlobalFlags } = BaseCommandTest;
    const argv = newArgv();
    argv.push('deployment', 'diagnostics', 'logs', '--deployment', deployment);
    argvPushGlobalFlags(argv, testName);
    return argv;
}
//# sourceMappingURL=one-shot-single.test.js.map