"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleReportingForTestsRun = handleReportingForTestsRun;
exports.parseOutReportOptions = parseOutReportOptions;
const constants_1 = require("../core/constants");
const TestResult_1 = require("../core/execution/TestResult");
const loggingProvider_1 = require("../providers/logging/loggingProvider");
const mochAwesomeReporter_1 = require("./mochAwesome/mochAwesomeReporter");
const playwright_reporter_1 = require("@mablhq/playwright-reporter");
const path_1 = __importDefault(require("path"));
async function handleReportingForTestsRun(reporter, testResults, apiClient, reportOptions, browser, fromPlanId, environmentId, applicationId, verbose) {
    let options;
    try {
        options = reportOptions ? parseOutReportOptions(reportOptions) : {};
    }
    catch (error) {
        throw new Error('Could not parse the supplied reporter options');
    }
    try {
        switch (reporter) {
            case constants_1.Reporter.Mochawesome:
                await (0, mochAwesomeReporter_1.generateMochAwesomeReportFromTestResults)(testResults, options);
                break;
            case constants_1.Reporter.Mabl:
                if (!browser) {
                    throw new Error('Browser is required for Mabl reporting');
                }
                await generateMablReportFromTestResults(testResults, options, apiClient, browser, fromPlanId, environmentId, applicationId, verbose);
                break;
            default:
                throw new Error(`Unsupported reporter options supplied: ${reporter}`);
        }
    }
    catch (error) {
        loggingProvider_1.logger.error(`Unable to create report for the test run using reporter: ${reporter} due to Error: ${error}`);
    }
}
async function generateMablReportFromTestResults(testResults, _options, apiClient, browser, fromPlanId, environmentId, applicationId, verbose) {
    if (testResults.testResults.length === 0) {
        return;
    }
    const workspaceId = testResults.testResults.some((result) => result.workspaceId)
        ? testResults.testResults[0].workspaceId
        : undefined;
    if (!workspaceId) {
        throw new Error('Workspace ID is required for Mabl reporting');
    }
    const reporterApiClient = new playwright_reporter_1.MablApiClient({
        httpClient: apiClient.httpClient,
        apiUrl: apiClient.baseApiUrl,
        log: (message) => {
            loggingProvider_1.logger.info(message);
            return;
        },
        logError: (message) => {
            loggingProvider_1.logger.error(message);
            return;
        },
    });
    const uploadClient = new playwright_reporter_1.UploadClient({
        uploadServiceUrl: new URL(apiClient.baseApiUrl),
        httpClient: apiClient.httpClient,
        debug: verbose,
    });
    const mablReporter = new playwright_reporter_1.MablReporter({
        apiClient: reporterApiClient,
        uploadClient,
        log: (message) => {
            loggingProvider_1.logger.debug(message);
        },
        logError: (message) => {
            loggingProvider_1.logger.error(message);
        },
        workspaceId,
        context: 'mabl_local',
        outputDir: verbose ? path_1.default.join(process.cwd(), 'mabl-output') : undefined,
    });
    let planRunId;
    if (fromPlanId) {
        planRunId = await mablReporter.createPlanRunToMabl({
            planId: fromPlanId,
            environmentId,
            applicationId,
        });
    }
    for (const result of testResults.testResults.filter((result) => shouldReportTestResult(result.status))) {
        const outcome = testResultStatusToReporterOutcome(result.status);
        const status = outcome === 'passed' ? 'passed' : 'failed';
        const steps = reporterStepsToMablExecutionSteps(result.stepResults);
        try {
            await mablReporter.createTestResult({
                workspace_id: workspaceId,
                started_time: result.startTime,
                completed_time: result.endTime,
                test_id: result.testId,
                test_type: 'browser',
                outcome,
                status: testResultStatusToReporterStatus(result.status),
                browser,
                parent_execution: planRunId,
            }, undefined, steps, status, environmentId, applicationId);
        }
        catch (error) {
            loggingProvider_1.logger.error(`Unable to create Mabl test result due to error: ${error}`);
        }
    }
    if (planRunId) {
        await mablReporter.finalizePlanRun(planRunId, testResults.success ? 'succeeded' : 'failed');
    }
}
function parseOutReportOptions(suppliedOptions) {
    const reporterOptions = {};
    const pairs = suppliedOptions.split(',');
    pairs.forEach((pair) => {
        const [key, value] = pair.split('=', 3);
        if (value.toLowerCase() === 'false' || value.toLowerCase() === 'true') {
            reporterOptions[key] = value.toLowerCase() === 'true';
        }
        else if (!Number.isNaN(Number(value))) {
            reporterOptions[key] = Number(key);
        }
        else {
            reporterOptions[key] = value;
        }
    });
    return reporterOptions;
}
function testResultStatusToReporterOutcome(status) {
    if (status === TestResult_1.TestResultStatus.passed) {
        return 'passed';
    }
    return 'failed';
}
function shouldReportTestResult(status) {
    return (status === TestResult_1.TestResultStatus.failed || status === TestResult_1.TestResultStatus.passed);
}
function testResultStatusToReporterStatus(status) {
    if (status === TestResult_1.TestResultStatus.passed) {
        return 'completed';
    }
    return 'failed';
}
function reporterStepsToMablExecutionSteps(steps) {
    if (!steps) {
        return [];
    }
    const result = [];
    for (const step of steps) {
        if (isExecutionStepResult(step)) {
            result.push(stepToMablExecutionStep(step));
        }
        else if (isFlowReporterInfo(step)) {
            result.push({
                title: step.description ?? '',
                startTime: step.startTime ? new Date(step.startTime).toISOString() : '',
                duration: step.duration ?? 0,
                status: 'passed',
                observations: [],
                category: step.isStepGroup ? 'step_group' : 'flow',
                rawCategory: step.isStepGroup ? 'step_group' : 'flow',
                steps: reporterStepsToMablExecutionSteps(step.steps),
                loopInfo: step.loopInfo
                    ? {
                        loopIndex: step.loopInfo.loopIndex,
                        loopTotal: step.loopInfo.loopCount,
                    }
                    : undefined,
            });
        }
    }
    return result;
}
function stepStepStatusToReporterStepStatus(status) {
    if (status === TestResult_1.StepStatus.Passed) {
        return 'passed';
    }
    if (status === TestResult_1.StepStatus.Failed) {
        return 'failed';
    }
    return 'skipped';
}
function stepToMablExecutionStep(step) {
    return {
        title: step.stepDescription ?? step.step?.description ?? '',
        startTime: step?.startTime ? new Date(step?.startTime).toISOString() : '',
        duration: step.duration ?? 0,
        status: stepStepStatusToReporterStepStatus(step.status),
        observations: [],
        category: 'step',
        rawCategory: 'step',
    };
}
function isExecutionStepResult(step) {
    return 'stepDescription' in step;
}
function isFlowReporterInfo(step) {
    return 'description' in step;
}
