var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
import { Resolver, Mutation, Query, Arg, Ctx, ObjectType, Field, PubSub, PubSubEngine, ID, Int } from 'type-graphql';
import { LogError, LogStatus } from '@memberjunction/core';
import { TestEngine } from '@memberjunction/testing-engine';
import { ResolverBase } from '../generic/ResolverBase.js';
import { PUSH_STATUS_UPDATES_TOPIC } from '../generic/PushStatusResolver.js';
let TestRunResult = class TestRunResult {
    success;
    errorMessage;
    executionTimeMs;
    result;
};
__decorate([
    Field(),
    __metadata("design:type", Boolean)
], TestRunResult.prototype, "success", void 0);
__decorate([
    Field({ nullable: true }),
    __metadata("design:type", String)
], TestRunResult.prototype, "errorMessage", void 0);
__decorate([
    Field({ nullable: true }),
    __metadata("design:type", Number)
], TestRunResult.prototype, "executionTimeMs", void 0);
__decorate([
    Field(),
    __metadata("design:type", String)
], TestRunResult.prototype, "result", void 0);
TestRunResult = __decorate([
    ObjectType()
], TestRunResult);
export { TestRunResult };
let TestSuiteRunResult = class TestSuiteRunResult {
    success;
    errorMessage;
    executionTimeMs;
    result;
};
__decorate([
    Field(),
    __metadata("design:type", Boolean)
], TestSuiteRunResult.prototype, "success", void 0);
__decorate([
    Field({ nullable: true }),
    __metadata("design:type", String)
], TestSuiteRunResult.prototype, "errorMessage", void 0);
__decorate([
    Field({ nullable: true }),
    __metadata("design:type", Number)
], TestSuiteRunResult.prototype, "executionTimeMs", void 0);
__decorate([
    Field(),
    __metadata("design:type", String)
], TestSuiteRunResult.prototype, "result", void 0);
TestSuiteRunResult = __decorate([
    ObjectType()
], TestSuiteRunResult);
export { TestSuiteRunResult };
let TestExecutionProgress = class TestExecutionProgress {
    currentStep;
    percentage;
    message;
    testName;
    driverType;
    oracleEvaluation;
};
__decorate([
    Field(),
    __metadata("design:type", String)
], TestExecutionProgress.prototype, "currentStep", void 0);
__decorate([
    Field(() => Int),
    __metadata("design:type", Number)
], TestExecutionProgress.prototype, "percentage", void 0);
__decorate([
    Field(),
    __metadata("design:type", String)
], TestExecutionProgress.prototype, "message", void 0);
__decorate([
    Field({ nullable: true }),
    __metadata("design:type", String)
], TestExecutionProgress.prototype, "testName", void 0);
__decorate([
    Field({ nullable: true }),
    __metadata("design:type", String)
], TestExecutionProgress.prototype, "driverType", void 0);
__decorate([
    Field({ nullable: true }),
    __metadata("design:type", String)
], TestExecutionProgress.prototype, "oracleEvaluation", void 0);
TestExecutionProgress = __decorate([
    ObjectType()
], TestExecutionProgress);
export { TestExecutionProgress };
let TestExecutionStreamMessage = class TestExecutionStreamMessage {
    sessionId;
    testRunId;
    type;
    progress;
    timestamp;
    testRun;
};
__decorate([
    Field(() => ID),
    __metadata("design:type", String)
], TestExecutionStreamMessage.prototype, "sessionId", void 0);
__decorate([
    Field(() => ID),
    __metadata("design:type", String)
], TestExecutionStreamMessage.prototype, "testRunId", void 0);
__decorate([
    Field(),
    __metadata("design:type", String)
], TestExecutionStreamMessage.prototype, "type", void 0);
__decorate([
    Field({ nullable: true }),
    __metadata("design:type", TestExecutionProgress)
], TestExecutionStreamMessage.prototype, "progress", void 0);
__decorate([
    Field(),
    __metadata("design:type", Date)
], TestExecutionStreamMessage.prototype, "timestamp", void 0);
TestExecutionStreamMessage = __decorate([
    ObjectType()
], TestExecutionStreamMessage);
export { TestExecutionStreamMessage };
let RunTestResolver = class RunTestResolver extends ResolverBase {
    async RunTest(testId, verbose = true, environment, tags, pubSub, { userPayload } = {}) {
        const startTime = Date.now();
        try {
            const user = this.GetUserFromPayload(userPayload);
            if (!user) {
                throw new Error('User context required');
            }
            LogStatus(`[RunTestResolver] Starting test execution: ${testId}`);
            const engine = TestEngine.Instance;
            await engine.Config(verbose, user);
            const progressCallback = pubSub ?
                this.createProgressCallback(pubSub, userPayload, testId) :
                undefined;
            const options = {
                verbose,
                environment,
                tags,
                progressCallback
            };
            const result = await engine.RunTest(testId, options, user);
            let finalResult;
            let allPassed = true;
            if (Array.isArray(result)) {
                allPassed = result.every(r => r.status === 'Passed');
                finalResult = {
                    testRunId: result[0]?.testRunId || '',
                    status: allPassed ? 'Passed' : 'Failed'
                };
                if (pubSub) {
                    for (const iterationResult of result) {
                        this.publishComplete(pubSub, userPayload, iterationResult);
                    }
                }
                LogStatus(`[RunTestResolver] Test completed: ${result.length} iterations, ${allPassed ? 'all passed' : 'some failed'} in ${Date.now() - startTime}ms`);
            }
            else {
                finalResult = result;
                allPassed = result.status === 'Passed';
                if (pubSub && result.testRunId) {
                    this.publishComplete(pubSub, userPayload, result);
                }
                LogStatus(`[RunTestResolver] Test completed: ${result.status} in ${Date.now() - startTime}ms`);
            }
            const executionTime = Date.now() - startTime;
            return {
                success: allPassed,
                result: JSON.stringify(result),
                executionTimeMs: executionTime
            };
        }
        catch (error) {
            const executionTime = Date.now() - startTime;
            const errorMsg = error.message;
            LogError(`[RunTestResolver] Test execution failed: ${errorMsg}`);
            if (pubSub) {
                this.publishError(pubSub, userPayload, testId, errorMsg);
            }
            return {
                success: false,
                errorMessage: errorMsg,
                result: JSON.stringify({}),
                executionTimeMs: executionTime
            };
        }
    }
    async RunTestSuite(suiteId, verbose = true, environment, parallel = false, tags, selectedTestIds, sequenceStart, sequenceEnd, pubSub, { userPayload } = {}) {
        const startTime = Date.now();
        try {
            const user = this.GetUserFromPayload(userPayload);
            if (!user) {
                throw new Error('User context required');
            }
            LogStatus(`[RunTestResolver] Starting suite execution: ${suiteId}`);
            const engine = TestEngine.Instance;
            await engine.Config(verbose, user);
            const progressCallback = pubSub ?
                this.createProgressCallback(pubSub, userPayload, suiteId) :
                undefined;
            let parsedSelectedTestIds;
            if (selectedTestIds) {
                try {
                    parsedSelectedTestIds = JSON.parse(selectedTestIds);
                }
                catch (e) {
                    LogError(`[RunTestResolver] Failed to parse selectedTestIds: ${selectedTestIds}`);
                }
            }
            const options = {
                verbose,
                environment,
                parallel,
                tags,
                selectedTestIds: parsedSelectedTestIds,
                sequenceStart,
                sequenceEnd,
                progressCallback
            };
            const result = await engine.RunSuite(suiteId, options, user);
            const executionTime = Date.now() - startTime;
            LogStatus(`[RunTestResolver] Suite completed: ${result.totalTests} tests in ${executionTime}ms`);
            return {
                success: result.status === 'Completed',
                result: JSON.stringify(result),
                executionTimeMs: executionTime
            };
        }
        catch (error) {
            const executionTime = Date.now() - startTime;
            const errorMsg = error.message;
            LogError(`[RunTestResolver] Suite execution failed: ${errorMsg}`);
            return {
                success: false,
                errorMessage: errorMsg,
                result: JSON.stringify({}),
                executionTimeMs: executionTime
            };
        }
    }
    async IsTestRunning(testId, { userPayload } = {}) {
        return false;
    }
    createProgressCallback(pubSub, userPayload, testId) {
        return (progress) => {
            LogStatus(`[RunTestResolver] Progress: ${progress.step} - ${progress.percentage}%`);
            const testRun = progress.metadata?.testRun;
            const progressMsg = {
                sessionId: userPayload.sessionId || '',
                testRunId: testRun?.ID || testId,
                type: 'progress',
                testRun: testRun ? testRun.GetAll() : undefined,
                progress: {
                    currentStep: progress.step,
                    percentage: progress.percentage,
                    message: progress.message,
                    testName: progress.metadata?.testName,
                    driverType: progress.metadata?.driverType,
                    oracleEvaluation: progress.metadata?.oracleType
                },
                timestamp: new Date()
            };
            this.publishProgress(pubSub, progressMsg, userPayload);
        };
    }
    publishProgress(pubSub, data, userPayload) {
        pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
            message: JSON.stringify({
                resolver: 'RunTestResolver',
                type: 'TestExecutionProgress',
                status: 'ok',
                data,
            }),
            sessionId: userPayload.sessionId,
        });
    }
    publishComplete(pubSub, userPayload, result) {
        pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
            message: JSON.stringify({
                resolver: 'RunTestResolver',
                type: 'TestExecutionComplete',
                status: 'ok',
                data: {
                    sessionId: userPayload.sessionId,
                    testRunId: result.testRunId,
                    type: 'complete',
                    result: JSON.stringify(result),
                    timestamp: new Date()
                },
            }),
            sessionId: userPayload.sessionId,
        });
    }
    publishError(pubSub, userPayload, testId, errorMsg) {
        pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
            message: JSON.stringify({
                resolver: 'RunTestResolver',
                type: 'TestExecutionError',
                status: 'error',
                data: {
                    sessionId: userPayload.sessionId,
                    testRunId: testId,
                    type: 'error',
                    errorMessage: errorMsg,
                    timestamp: new Date()
                },
            }),
            sessionId: userPayload.sessionId,
        });
    }
};
__decorate([
    Mutation(() => TestRunResult),
    __param(0, Arg('testId')),
    __param(1, Arg('verbose', { nullable: true })),
    __param(2, Arg('environment', { nullable: true })),
    __param(3, Arg('tags', { nullable: true })),
    __param(4, PubSub()),
    __param(5, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, Boolean, String, String, PubSubEngine, Object]),
    __metadata("design:returntype", Promise)
], RunTestResolver.prototype, "RunTest", null);
__decorate([
    Mutation(() => TestSuiteRunResult),
    __param(0, Arg('suiteId')),
    __param(1, Arg('verbose', { nullable: true })),
    __param(2, Arg('environment', { nullable: true })),
    __param(3, Arg('parallel', { nullable: true })),
    __param(4, Arg('tags', { nullable: true })),
    __param(5, Arg('selectedTestIds', { nullable: true })),
    __param(6, Arg('sequenceStart', () => Int, { nullable: true })),
    __param(7, Arg('sequenceEnd', () => Int, { nullable: true })),
    __param(8, PubSub()),
    __param(9, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, Boolean, String, Boolean, String, String, Number, Number, PubSubEngine, Object]),
    __metadata("design:returntype", Promise)
], RunTestResolver.prototype, "RunTestSuite", null);
__decorate([
    Query(() => Boolean),
    __param(0, Arg('testId')),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, Object]),
    __metadata("design:returntype", Promise)
], RunTestResolver.prototype, "IsTestRunning", null);
RunTestResolver = __decorate([
    Resolver()
], RunTestResolver);
export { RunTestResolver };
//# sourceMappingURL=RunTestResolver.js.map