// SPDX-License-Identifier: Apache-2.0
import { Flags } from '../../../../src/commands/flags.js';
import { getTestCacheDirectory } from '../../../test-utility.js';
import { container } from 'tsyringe-neo';
import { InjectTokens } from '../../../../src/core/dependency-injection/inject-tokens.js';
import { DeploymentCommandDefinition } from '../../../../src/commands/command-definitions/deployment-command-definition.js';
import { Argv } from '../../../helpers/argv-wrapper.js';
import { NamespaceName } from '../../../../src/types/namespace/namespace-name.js';
import { getEnvironmentVariable } from '../../../../src/core/constants.js';
import { ConsensusCommandDefinition } from '../../../../src/commands/command-definitions/consensus-command-definition.js';
import { Templates } from '../../../../src/core/templates.js';
import { PathEx } from '../../../../src/business/utils/path-ex.js';
import { main } from '../../../../src/index.js';
import fs from 'node:fs';
export class BaseCommandTest {
    static newArgv() {
        return ['${PATH}/node', '${SOLO_ROOT}/solo.ts'];
    }
    static optionFromFlag(flag) {
        return `--${flag.name}`;
    }
    static argvPushGlobalFlags(argv, testName, shouldSetTestCacheDirectory = false, shouldSetChartDirectory = false) {
        argv.push(BaseCommandTest.optionFromFlag(Flags.devMode), BaseCommandTest.optionFromFlag(Flags.quiet));
        const soloChartsDirectory = getEnvironmentVariable('SOLO_CHARTS_DIR');
        if (shouldSetChartDirectory && soloChartsDirectory && soloChartsDirectory !== '') {
            argv.push(BaseCommandTest.optionFromFlag(Flags.chartDirectory), process.env.SOLO_CHARTS_DIR);
        }
        if (shouldSetTestCacheDirectory) {
            argv.push(BaseCommandTest.optionFromFlag(Flags.cacheDir), getTestCacheDirectory(testName));
        }
        return argv;
    }
    /**
     * Collects diagnostic logs using the deployment diagnostics command.
     * This is a shared helper used by both test patterns.
     */
    static async collectDiagnosticLogs(testName, testLogger, deployment) {
        try {
            testLogger.info(`${testName}: Collecting diagnostic logs...`);
            // Create proper Argv object
            const argv = Argv.getDefaultArgv(NamespaceName.of(testName), testName);
            argv.setArg(Flags.deployment, deployment);
            argv.setCommand(DeploymentCommandDefinition.COMMAND_NAME, DeploymentCommandDefinition.DIAGNOSTICS_SUBCOMMAND_NAME, DeploymentCommandDefinition.DIAGNOSTICS_LOGS);
            const nodeCmd = container.resolve(InjectTokens.NodeCommand);
            await nodeCmd.handlers.logs(argv.build());
            testLogger.info(`${testName}: Diagnostic logs collected successfully`);
        }
        catch (error) {
            testLogger.error(`${testName}: Error collecting diagnostic logs: ${error}`);
            if (error instanceof Error && error.stack) {
                testLogger.error(`${testName}: Stack trace:\n${error.stack}`);
            }
        }
    }
    static async collectJavaFlightRecorderLogs(testName, testLogger, deployment, nodeAlias) {
        try {
            testLogger.info(`${testName}: Collecting jfr logs...`);
            // Create proper Argv object
            const argv = Argv.getDefaultArgv(NamespaceName.of(testName), testName);
            argv.setArg(Flags.deployment, deployment);
            argv.setArg(Flags.nodeAlias, nodeAlias);
            argv.setCommand(ConsensusCommandDefinition.COMMAND_NAME, ConsensusCommandDefinition.NODE_SUBCOMMAND_NAME, ConsensusCommandDefinition.COLLECT_JFR);
            const nodeCmd = container.resolve(InjectTokens.NodeCommand);
            await nodeCmd.handlers.collectJavaFlightRecorderLogs(argv.build());
            testLogger.info(`${testName}: Java Flight Recorder logs for node ${nodeAlias} collected successfully`);
        }
        catch (error) {
            testLogger.error(`${testName}: Error collecting Java Flight Recorder logs for node  ${nodeAlias}: ${error}`);
            if (error instanceof Error && error.stack) {
                testLogger.error(`${testName}: Stack trace:\n${error.stack}`);
            }
        }
    }
    /**
     * Sets up an after() hook for diagnostic log collection in E2E tests.
     * Call this within your test suite describe block.
     */
    static async setupDiagnosticLogCollection(options) {
        const { testName, testLogger, deployment } = options;
        await BaseCommandTest.collectDiagnosticLogs(testName, testLogger, deployment);
    }
    /**
     * Sets up an after() hook for diagnostic log collection in E2E tests.
     * Call this within your test suite describe block.
     */
    static setupJavaFlightRecorderLogCollection(options) {
        const { testName, testLogger, deployment } = options;
        const promises = [];
        for (let index = 0; index < options.consensusNodesCount; index++) {
            const nodeAlias = Templates.renderNodeAliasFromNumber(index + 1);
            promises.push(BaseCommandTest.collectJavaFlightRecorderLogs(testName, testLogger, deployment, nodeAlias));
        }
        return Promise.all(promises);
    }
    static async runMainAndCaptureOutputToJson(argv, options) {
        const stdoutChunks = [];
        const stderrChunks = [];
        const outputSubdirectory = options.outputSubdirectory ?? 'command-output';
        const originalStdoutWrite = process.stdout.write.bind(process.stdout);
        const originalStderrWrite = process.stderr.write.bind(process.stderr);
        process.stdout.write = ((chunk, encoding, callback) => {
            stdoutChunks.push(typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString(encoding));
            if (encoding === undefined) {
                return callback ? originalStdoutWrite(chunk, callback) : originalStdoutWrite(chunk);
            }
            return callback ? originalStdoutWrite(chunk, encoding, callback) : originalStdoutWrite(chunk, encoding);
        });
        process.stderr.write = ((chunk, encoding, callback) => {
            stderrChunks.push(typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString(encoding));
            if (encoding === undefined) {
                return callback ? originalStderrWrite(chunk, callback) : originalStderrWrite(chunk);
            }
            return callback ? originalStderrWrite(chunk, encoding, callback) : originalStderrWrite(chunk, encoding);
        });
        try {
            await main(argv);
        }
        finally {
            process.stdout.write = originalStdoutWrite;
            process.stderr.write = originalStderrWrite;
        }
        const outputDirectory = PathEx.join(getTestCacheDirectory(options.testName), outputSubdirectory);
        fs.mkdirSync(outputDirectory, { recursive: true });
        const outputFilePath = PathEx.join(outputDirectory, options.outputFileName);
        const payload = {
            timestamp: new Date().toISOString(),
            argv,
            stdout: stdoutChunks.join(''),
            stderr: stderrChunks.join(''),
            ...options.metadata,
        };
        fs.writeFileSync(outputFilePath, JSON.stringify(payload, undefined, 2), 'utf8');
        return {
            stdout: payload.stdout,
            stderr: payload.stderr,
            outputFilePath,
        };
    }
}
//# sourceMappingURL=base-command-test.js.map