import { execAsync } from '../../../utils.js';
import { createModuleLogger } from '../../../logger.js';
import { existsSync, readFileSync, unlinkSync } from 'fs';
import { tmpdir } from 'os';
import path from 'path';
const logger = createModuleLogger('SwiftPackageTester');
/**
 * Handles testing Swift packages (Single Responsibility: Testing)
 */
export class SwiftPackageTester {
    /**
     * Test a Swift package
     */
    async test(packagePath, options = {}) {
        const startTime = Date.now();
        const { filter, configuration = 'Debug' } = options;
        // Generate unique xunit output file path
        const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
        const xunitPath = path.join(tmpdir(), `swift-test-${timestamp}.xml`);
        // Convert to lowercase for swift command
        const configFlag = configuration.toLowerCase();
        let command = `swift test --package-path "${packagePath}" -c ${configFlag}`;
        if (filter) {
            command += ` --filter "${filter}"`;
        }
        // Add xunit output for XCTest results
        command += ` --xunit-output "${xunitPath}"`;
        logger.debug({ command, xunitPath }, 'Test command with xunit output');
        try {
            const { stdout, stderr } = await execAsync(command, {
                maxBuffer: 10 * 1024 * 1024
            });
            const output = stdout + (stderr ? `\n${stderr}` : '');
            const duration = Date.now() - startTime;
            // Parse xunit XML
            if (existsSync(xunitPath)) {
                try {
                    const xmlContent = readFileSync(xunitPath, 'utf8');
                    logger.debug({ xunitPath }, 'Found xunit output file');
                    // Parse the xunit XML
                    const testsMatch = xmlContent.match(/tests="(\d+)"/);
                    const failuresMatch = xmlContent.match(/failures="(\d+)"/);
                    if (testsMatch && failuresMatch) {
                        const totalTests = parseInt(testsMatch[1], 10);
                        const failures = parseInt(failuresMatch[1], 10);
                        const passed = totalTests - failures;
                        // Extract failing test names
                        const failingTestMatches = xmlContent.matchAll(/testcase[^>]+name="([^"]+)"[^>]*>\s*<failure/g);
                        const failingTests = [];
                        for (const match of failingTestMatches) {
                            failingTests.push(match[1]);
                        }
                        logger.info({
                            packagePath,
                            passed,
                            failed: failures,
                            failingTests,
                            duration
                        }, 'Tests completed (parsed from xunit)');
                        return {
                            passed,
                            failed: failures,
                            success: failures === 0,
                            failingTests: failingTests.length > 0 ? failingTests : undefined,
                            output,
                            duration
                        };
                    }
                    else {
                        throw new Error('Failed to parse xunit XML: tests/failures attributes not found');
                    }
                }
                catch (xmlError) {
                    logger.error({ error: xmlError.message }, 'Failed to parse xunit file');
                    throw new Error(`Failed to parse xunit output: ${xmlError.message}`);
                }
                finally {
                    // Clean up xunit file
                    try {
                        unlinkSync(xunitPath);
                        // Also clean up Swift Testing output file if it exists
                        const swiftTestingPath = xunitPath.replace('.xml', '-swift-testing.xml');
                        if (existsSync(swiftTestingPath)) {
                            unlinkSync(swiftTestingPath);
                        }
                    }
                    catch {
                        // Ignore cleanup errors
                    }
                }
            }
            else {
                throw new Error('Swift test did not generate xunit output file');
            }
        }
        catch (error) {
            const duration = Date.now() - startTime;
            logger.error({ error: error.message, packagePath }, 'Tests failed');
            const output = (error.stdout || '') + (error.stderr ? `\n${error.stderr}` : '');
            // Try to parse xunit output even on failure
            if (existsSync(xunitPath)) {
                try {
                    const xmlContent = readFileSync(xunitPath, 'utf8');
                    const testsMatch = xmlContent.match(/tests="(\d+)"/);
                    const failuresMatch = xmlContent.match(/failures="(\d+)"/);
                    if (testsMatch && failuresMatch) {
                        const totalTests = parseInt(testsMatch[1], 10);
                        const failures = parseInt(failuresMatch[1], 10);
                        const passed = totalTests - failures;
                        const failingTestMatches = xmlContent.matchAll(/testcase[^>]+name="([^"]+)"[^>]*>\s*<failure/g);
                        const failingTests = [];
                        for (const match of failingTestMatches) {
                            failingTests.push(match[1]);
                        }
                        return {
                            passed,
                            failed: failures,
                            success: false,
                            failingTests: failingTests.length > 0 ? failingTests : undefined,
                            output,
                            duration
                        };
                    }
                }
                catch {
                    // Ignore parse errors
                }
                finally {
                    try {
                        unlinkSync(xunitPath);
                        const swiftTestingPath = xunitPath.replace('.xml', '-swift-testing.xml');
                        if (existsSync(swiftTestingPath)) {
                            unlinkSync(swiftTestingPath);
                        }
                    }
                    catch {
                        // Ignore cleanup errors
                    }
                }
            }
            return {
                passed: 0,
                failed: 1,
                success: false,
                output,
                error: error.message,
                duration
            };
        }
    }
}
//# sourceMappingURL=SwiftPackageTester.js.map