import {
    getGatewayJson,
    handleTestAssets,
    testAssetsForEndpoint,
    handleTestProjects,
    handleTestWarnings,
    writeArchive
} from './helpers/test-action-helper.js';
import { TestOptionsModel } from '../model/studio/command-options/test-options-model.js';
import { DebugManager } from '../debug/debug-manager.js';
import { showError } from '../helpers/common/message-helper.js';
import { ENDPOINT_ARGUMENT_NOT_AVAILABLE, TEST_EXECUTION_FAILED } from '../constants/message-constants.js';
import { executeTest, getTestErrorData } from '../testers/project/projects-testers.js';
import { authTokenPrompt, passwordPrompt } from '../prompts/input-prompt.js';
import { updateEnvironmentAssetInZip, parseEnvInput } from '../helpers/apim/env-helper.js';
import { DEPENDENCY_DIRECTORY } from '../constants/app-constants.js';
import { TestCaseFailureError } from '../Errors/test-case-failure-error.js';
import { generateFileInRootDir } from '../helpers/common/fs-helper.js';
import { GatewaysJson } from '@apic/studio-shared';
import { TestOutputBuffers } from '../model/studio/test-response-model.js';


export const setupDebugManager = (debug: boolean): DebugManager => {

    const debugManager = DebugManager.getInstance();
    if (debug) {
        debugManager.setDebugEnabled(true);
    }
    return debugManager;
};

const validateEndpointWithNames = (options: TestOptionsModel) => {
    if (options.endpoints && !options.names) {
        throw new Error(ENDPOINT_ARGUMENT_NOT_AVAILABLE);
    }
};


const getAssets = (options: TestOptionsModel, projects: string, localDir: string, gatewayJson: GatewaysJson) => {
    return options.endpoints
        ? testAssetsForEndpoint(options, projects, localDir)
        : handleTestAssets(options, projects, localDir, gatewayJson);
};


const testAction = async (projects: string, options: TestOptionsModel) => {
    try {
        const localDir = options.localDir;
        const gatewayPassword = options.target ? (options.username?await passwordPrompt(options.password): await authTokenPrompt(options.authToken) ): '';
        options.password=gatewayPassword;
        const gatewayJson = await getGatewayJson(options, gatewayPassword);
        const debug= options.debug;
        const debugManager = setupDebugManager(debug);


        handleTestWarnings(projects, options);
        validateEndpointWithNames(options);

        let outputBuffers: TestOutputBuffers;

        if (options.names && !options.all) {
            outputBuffers = await getAssets(options, projects, localDir, gatewayJson);
        } else {
            outputBuffers = await handleTestProjects(options, projects, localDir, gatewayJson);
        }

        if (outputBuffers.testZipBuffer) {
            if (options.env) {
                const envMap = parseEnvInput(options.env);
                outputBuffers.testZipBuffer = await updateEnvironmentAssetInZip(outputBuffers.testZipBuffer, envMap, DEPENDENCY_DIRECTORY);
            }

            if (debugManager.isDebugEnabled()) {
                await writeArchive(projects, options.all, options.names, outputBuffers.testZipBuffer, outputBuffers.buildZipBuffer);
            }

            await executeTest(outputBuffers.testZipBuffer);
        }

    } catch (error) {
        if (error instanceof TestCaseFailureError) {
            showError(`\n${error.message}`);
        } else {
            showError(`\n${TEST_EXECUTION_FAILED} ${(error as Error).message}`);
            await generateFileInRootDir(getTestErrorData(error as Error));
        }
        process.exit(1);
    }
};

export { testAction };
