"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
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 __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var TestRunCommand_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TestRunCommand = void 0;
const common_1 = require("@nestjs/common");
const nest_commander_1 = require("nest-commander");
const path = __importStar(require("path"));
const module_metadata_helper_service_1 = require("../helpers/module-metadata-helper.service");
const console_reporter_1 = require("../testing/reporter/console-reporter");
const webhook_reporter_1 = require("../testing/reporter/webhook-reporter");
const run_from_metadata_1 = require("../testing/runner/run-from-metadata");
const spec_registry_1 = require("../testing/core/spec-registry");
let TestRunCommand = TestRunCommand_1 = class TestRunCommand extends nest_commander_1.CommandRunner {
    constructor(moduleMetadataHelperService) {
        super();
        this.moduleMetadataHelperService = moduleMetadataHelperService;
        this.logger = new common_1.Logger(TestRunCommand_1.name);
    }
    async run(passedParam, options) {
        try {
            const moduleName = options?.moduleName ?? options?.module ?? passedParam?.[0];
            if (!moduleName) {
                this.logger.error('Module name is required. Use --module or pass it as the first argument.');
                return;
            }
            const metadataPath = await this.moduleMetadataHelperService.getModuleMetadataFilePath(moduleName);
            if (!metadataPath) {
                this.logger.error(`Unable to resolve metadata path for module: ${moduleName}`);
                return;
            }
            const metadata = await this.moduleMetadataHelperService.getModuleMetadataConfiguration(metadataPath);
            if (!metadata?.testing) {
                this.logger.error(`No testing configuration found in metadata: ${metadataPath}`);
                return;
            }
            const listSpecs = options?.listSpecs ?? false;
            const specEntries = Array.isArray(metadata.testing?.specs)
                ? metadata.testing.specs
                : [];
            if (listSpecs) {
                const registry = new spec_registry_1.SpecRegistry();
                if (specEntries.length) {
                    loadSpecRegistrations(specEntries, metadataPath, registry);
                }
                printSpecList(registry.list());
                return;
            }
            if (!metadata?.testing?.scenarios || !Array.isArray(metadata.testing.scenarios)) {
                this.logger.error(`No testing.scenarios found in metadata: ${metadataPath}`);
                return;
            }
            const scenarioIds = splitCsv(options?.scenarioIds);
            const includeTags = splitCsv(options?.includeTags);
            const skipScenarioIds = splitCsv(options?.skipScenarioIds);
            const reporterName = options?.reporter ?? 'console';
            if (reporterName !== 'console') {
                this.logger.error(`Unsupported reporter: ${reporterName}. Use "console".`);
                return;
            }
            const apiBaseUrl = options?.apiBaseUrl ?? process.env.BASE_URL;
            const uiBaseUrl = options?.uiBaseUrl ?? process.env.FRONTEND_BASE_URL;
            const headless = options?.headless ?? true;
            const printApiLogs = options?.printApiLogs ?? false;
            const webhookUrl = process.env.SOLIDCTL_WEBHOOK_URL;
            const runName = options?.runName ?? `run-${Date.now()}`;
            const reporter = webhookUrl
                ? new webhook_reporter_1.WebhookReporter(webhookUrl, runName)
                : new console_reporter_1.ConsoleReporter();
            try {
                await (0, run_from_metadata_1.runFromMetadata)({
                    metadata: metadata,
                    scenarioIds,
                    includeTags,
                    skipScenarioIds,
                    reporter,
                    api: apiBaseUrl ? { baseUrl: apiBaseUrl } : undefined,
                    ui: { baseUrl: uiBaseUrl, headless },
                    defaults: {
                        timeoutMs: options?.timeoutMs,
                        retries: options?.retries,
                    },
                    options: { printApiLogs },
                    specs: specEntries.length
                        ? (registry) => loadSpecRegistrations(specEntries, metadataPath, registry)
                        : undefined,
                });
            }
            catch (err) {
                this.logger.error('Run tests command failed');
                console.error('Run tests command failed');
                process.exitCode = 1;
            }
            finally {
                if (reporter instanceof webhook_reporter_1.WebhookReporter) {
                    await reporter.flush(Number(process.exitCode ?? 0));
                }
            }
            return;
        }
        catch (err) {
            this.logger.error('Run tests command failed');
            console.error('Run tests command failed');
            process.exitCode = 1;
            return;
        }
    }
    parseModule(val) {
        return val;
    }
    parseScenarioIds(val) {
        return val;
    }
    parseIncludeTags(val) {
        return val;
    }
    parseSkipScenarioIds(val) {
        return val;
    }
    parseReporter(val) {
        return val;
    }
    parseListSpecs(val) {
        if (val === undefined)
            return true;
        return val === 'false' ? false : true;
    }
    parsePrintApiLogs(val) {
        if (val === undefined)
            return true;
        return val === 'false' ? false : true;
    }
    parseApiBaseUrl(val) {
        return val;
    }
    parseUiBaseUrl(val) {
        return val;
    }
    parseHeadless(val) {
        return val === 'false' ? false : true;
    }
    parseTimeoutMs(val) {
        return Number(val);
    }
    parseRetries(val) {
        return Number(val);
    }
    parseRunName(val) {
        return val;
    }
};
exports.TestRunCommand = TestRunCommand;
__decorate([
    (0, nest_commander_1.Option)({
        flags: '-m, --module [module name]',
        description: 'Module name to load metadata from.',
        required: false,
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", String)
], TestRunCommand.prototype, "parseModule", null);
__decorate([
    (0, nest_commander_1.Option)({
        flags: '--scenario-ids [ids]',
        description: 'Comma-separated list of scenario ids to run.',
        required: false,
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", String)
], TestRunCommand.prototype, "parseScenarioIds", null);
__decorate([
    (0, nest_commander_1.Option)({
        flags: '--include-tags [tags]',
        description: 'Comma-separated list of tags; scenario must include all.',
        required: false,
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", String)
], TestRunCommand.prototype, "parseIncludeTags", null);
__decorate([
    (0, nest_commander_1.Option)({
        flags: '--skip-scenario-ids [ids]',
        description: 'Comma-separated list of scenario ids to skip.',
        required: false,
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", String)
], TestRunCommand.prototype, "parseSkipScenarioIds", null);
__decorate([
    (0, nest_commander_1.Option)({
        flags: '--reporter [name]',
        description: 'Reporter name (currently only "console").',
        required: false,
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", String)
], TestRunCommand.prototype, "parseReporter", null);
__decorate([
    (0, nest_commander_1.Option)({
        flags: '--list-specs [true|false]',
        description: 'List registered test specs and exit.',
        required: false,
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Boolean)
], TestRunCommand.prototype, "parseListSpecs", null);
__decorate([
    (0, nest_commander_1.Option)({
        flags: '--print-api-logs [true|false]',
        description: 'Print full API request/response logs for api.request steps.',
        required: false,
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Boolean)
], TestRunCommand.prototype, "parsePrintApiLogs", null);
__decorate([
    (0, nest_commander_1.Option)({
        flags: '--api-base-url [url]',
        description: 'API base URL (defaults to process.env.BASE_URL).',
        required: false,
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", String)
], TestRunCommand.prototype, "parseApiBaseUrl", null);
__decorate([
    (0, nest_commander_1.Option)({
        flags: '--ui-base-url [url]',
        description: 'UI base URL (defaults to process.env.FRONTEND_BASE_URL).',
        required: false,
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", String)
], TestRunCommand.prototype, "parseUiBaseUrl", null);
__decorate([
    (0, nest_commander_1.Option)({
        flags: '--headless [true|false]',
        description: 'Run UI browser in headless mode (default: true).',
        required: false,
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Boolean)
], TestRunCommand.prototype, "parseHeadless", null);
__decorate([
    (0, nest_commander_1.Option)({
        flags: '--timeout-ms [number]',
        description: 'Default scenario timeout in milliseconds.',
        required: false,
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Number)
], TestRunCommand.prototype, "parseTimeoutMs", null);
__decorate([
    (0, nest_commander_1.Option)({
        flags: '--retries [number]',
        description: 'Default scenario retries.',
        required: false,
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Number)
], TestRunCommand.prototype, "parseRetries", null);
__decorate([
    (0, nest_commander_1.Option)({
        flags: '--run-name [name]',
        description: 'Logical name for this test run (used by webhook reporter).',
        required: false,
    }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", String)
], TestRunCommand.prototype, "parseRunName", null);
exports.TestRunCommand = TestRunCommand = TestRunCommand_1 = __decorate([
    (0, nest_commander_1.SubCommand)({
        name: 'run',
        description: 'Run testing scenarios from module metadata.',
    }),
    __metadata("design:paramtypes", [module_metadata_helper_service_1.ModuleMetadataHelperService])
], TestRunCommand);
function splitCsv(value) {
    if (!value)
        return undefined;
    const items = value
        .split(',')
        .map((item) => item.trim())
        .filter(Boolean);
    return items.length ? items : undefined;
}
function resolveSpecPath(entry, metadataPath) {
    if (path.isAbsolute(entry)) {
        return entry;
    }
    if (entry.startsWith('.')) {
        return path.resolve(path.dirname(metadataPath), entry);
    }
    return path.resolve(process.cwd(), entry);
}
function loadSpecRegistrations(entries, metadataPath, registry) {
    for (const entry of entries) {
        const resolved = resolveSpecPath(entry, metadataPath);
        let mod;
        try {
            mod = require(resolved);
        }
        catch (err) {
            const message = err?.message ?? String(err);
            throw new Error(`Failed to load test spec module "${entry}" resolved to "${resolved}": ${message}`);
        }
        const register = mod?.registerTestSpecs ?? mod?.default ?? mod;
        if (typeof register !== 'function') {
            throw new Error(`Test spec module "${entry}" did not export a register function (expected "registerTestSpecs" or default export).`);
        }
        register(registry);
    }
}
function printSpecList(specIds) {
    if (!specIds.length) {
        console.log('No test specs registered.');
        return;
    }
    console.log('Registered test specs:');
    for (const id of specIds) {
        console.log(`- ${id}`);
    }
}
//# sourceMappingURL=run-tests.command.js.map