import * as fs from 'node:fs/promises';
import { XMLParser } from 'fast-xml-parser';
function toNumber(value) {
    if (value === undefined)
        return 0;
    if (typeof value === 'number')
        return value;
    return Number.parseInt(value, 10) || 0;
}
function toFloat(value) {
    if (value === undefined)
        return 0;
    if (typeof value === 'number')
        return value;
    return Number.parseFloat(value) || 0;
}
function extractFailureMessage(failure) {
    if (!failure)
        return 'Unknown failure';
    if (typeof failure === 'string')
        return failure;
    return failure['@_message'] || failure['#text'] || 'Unknown failure';
}
function processTestCase(testcase, failures) {
    const testName = testcase['@_name'] || 'Unknown test';
    if (testcase.failure) {
        failures.push({
            testName,
            message: extractFailureMessage(testcase.failure),
        });
    }
    if (testcase.error) {
        failures.push({
            testName,
            message: extractFailureMessage(testcase.error),
        });
    }
}
function processTestSuite(suite, result) {
    result.total += toNumber(suite['@_tests']);
    result.skipped += toNumber(suite['@_skipped']);
    result.duration += toFloat(suite['@_time']);
    const testcases = suite.testcase;
    if (!testcases)
        return;
    const cases = Array.isArray(testcases) ? testcases : [testcases];
    for (const testcase of cases) {
        processTestCase(testcase, result.failures);
    }
}
export function parseJUnit(content) {
    const parser = new XMLParser({
        ignoreAttributes: false,
        attributeNamePrefix: '@_',
    });
    const doc = parser.parse(content);
    const result = {
        total: 0,
        passed: 0,
        skipped: 0,
        duration: 0,
        failures: [],
    };
    // Handle <testsuites> wrapper
    if (doc.testsuites) {
        const suites = doc.testsuites.testsuite;
        if (suites) {
            const suiteArray = Array.isArray(suites) ? suites : [suites];
            for (const suite of suiteArray) {
                processTestSuite(suite, result);
            }
        }
        // Use aggregate counts if available
        if (doc.testsuites['@_tests']) {
            result.total = toNumber(doc.testsuites['@_tests']);
            result.skipped = toNumber(doc.testsuites['@_skipped']);
            result.duration = toFloat(doc.testsuites['@_time']);
        }
    }
    // Handle single <testsuite> at root
    else if (doc.testsuite) {
        processTestSuite(doc.testsuite, result);
    }
    // Calculate passed count
    result.passed = result.total - result.failures.length - result.skipped;
    return result;
}
export class GitHubReportCapability {
    summary;
    annotations;
    constructor(summary, annotations) {
        this.summary = summary;
        this.annotations = annotations;
    }
    async process(op, taskName) {
        switch (op.reportType) {
            case 'junit':
                await this.processJUnit(op.path, taskName);
                break;
            case 'coverage':
                await this.processCoverage(op.path, taskName);
                break;
        }
    }
    async processJUnit(path, taskName) {
        const content = await fs.readFile(path, 'utf-8');
        const result = parseJUnit(content);
        // Create annotations for failures
        for (const failure of result.failures) {
            this.annotations.emit({
                kind: 'annotate',
                level: 'error',
                message: `${failure.testName}: ${failure.message}`,
                location: failure.file ? { file: failure.file, line: failure.line } : undefined,
            });
        }
        // Add to summary
        const icon = result.failures.length === 0 ? '\u2705' : '\u274C';
        let md = `#### Test Results ${icon}\n\n`;
        md += `- **Total:** ${result.total}\n`;
        md += `- **Passed:** ${result.passed}\n`;
        md += `- **Failed:** ${result.failures.length}\n`;
        md += `- **Skipped:** ${result.skipped}\n`;
        md += `- **Duration:** ${result.duration}s\n`;
        if (result.failures.length > 0) {
            md += '\n**Failures:**\n';
            for (const f of result.failures) {
                md += `- \`${f.testName}\`: ${f.message}\n`;
            }
        }
        this.summary.writeTaskSummary(taskName, md);
    }
    async processCoverage(path, taskName) {
        // Try to parse coverage summary
        try {
            const content = await fs.readFile(path, 'utf-8');
            // Try JSON format (lcov-summary or similar)
            if (path.endsWith('.json')) {
                const data = JSON.parse(content);
                let md = '#### Coverage Report\n\n';
                if (data.total) {
                    md += `- **Lines:** ${data.total.lines?.pct ?? 'N/A'}%\n`;
                    md += `- **Branches:** ${data.total.branches?.pct ?? 'N/A'}%\n`;
                    md += `- **Functions:** ${data.total.functions?.pct ?? 'N/A'}%\n`;
                    md += `- **Statements:** ${data.total.statements?.pct ?? 'N/A'}%\n`;
                }
                this.summary.writeTaskSummary(taskName, md);
            }
        }
        catch {
            // Silently ignore coverage parsing errors
        }
    }
}
//# sourceMappingURL=reports.js.map