"""Top-level test result orchestrator.

Coordinates XML, SQLite, binary, and merge parsers to produce
a unified ``TestResults`` object.
"""

from __future__ import annotations

import logging
from pathlib import Path
from typing import TYPE_CHECKING

from ..runtime._codeflash_wrap_decorator import get_run_tmp_file
from ._data_parsers import (
    parse_sqlite_test_results,
    parse_test_return_values_bin,
)
from ._result_merger import merge_test_results
from ._stdout_parsers import parse_test_failures_from_stdout
from ._xml_parser import parse_test_xml
from .models import TestResults

if TYPE_CHECKING:
    import subprocess

    from .models import TestConfig, TestFiles

log = logging.getLogger(__name__)


def parse_test_results(
    test_xml_path: Path,
    test_files: TestFiles,
    test_config: TestConfig,
    optimization_iteration: int,
    run_result: subprocess.CompletedProcess[str] | None = None,
) -> TestResults:
    """Parse and merge all test result sources."""
    xml_results = parse_test_xml(
        test_xml_path,
        test_files,
        test_config,
        run_result,
    )

    # Parse SQLite results
    data_results = TestResults()
    sql_file = get_run_tmp_file(
        Path(f"test_return_values_{optimization_iteration}.sqlite"),
    )
    if sql_file.exists():
        data_results = parse_sqlite_test_results(
            sql_file, test_files, test_config
        )

    # Parse binary pickle results
    bin_file = get_run_tmp_file(
        Path(f"test_return_values_{optimization_iteration}.bin"),
    )
    if bin_file.exists():
        bin_results = parse_test_return_values_bin(
            bin_file, test_files, test_config
        )
        for result in bin_results:
            data_results.add(result)

    # Cleanup temp files
    bin_file.unlink(missing_ok=True)
    sql_file.unlink(missing_ok=True)
    get_run_tmp_file(Path("pytest_results.xml")).unlink(
        missing_ok=True,
    )

    # Merge XML + data results
    results = merge_test_results(
        xml_results,
        data_results,
    )

    # Capture stdout for perf/concurrency marker parsing
    if run_result:
        results.perf_stdout = run_result.stdout
        try:
            results.test_failures = parse_test_failures_from_stdout(
                run_result.stdout,
            )
        except Exception:
            log.exception("Failed to parse test failures from stdout")

    return results
