"""Post-round summary: run tests, snapshot project status, report.

Provides a single async function that executes the post-round checklist
and returns a combined summary dict.
"""

from __future__ import annotations

import asyncio
import logging
import re

import asyncpg

logger = logging.getLogger(__name__)

# Regex to parse pytest summary line, e.g. "5 passed, 2 failed, 1 error"
_PYTEST_SUMMARY = re.compile(
    r"(?:(\d+)\s+passed)?"
    r"(?:,?\s*(\d+)\s+failed)?"
    r"(?:,?\s*(\d+)\s+error(?:s)?)?"
)


def parse_pytest_output(output: str) -> dict:
    """Parse pytest stdout for pass/fail/error counts.

    Returns {"passed": N, "failed": M, "errors": E, "total": T}.
    """
    passed = 0
    failed = 0
    errors = 0

    # Look for the short test summary / final line
    for line in reversed(output.splitlines()):
        line = line.strip()
        if not line:
            continue
        # pytest outputs lines like "=== 5 passed, 2 failed in 1.23s ==="
        # or "=== 5 passed in 0.05s ==="
        if "passed" in line or "failed" in line or "error" in line:
            m_passed = re.search(r"(\d+)\s+passed", line)
            m_failed = re.search(r"(\d+)\s+failed", line)
            m_errors = re.search(r"(\d+)\s+error", line)
            if m_passed:
                passed = int(m_passed.group(1))
            if m_failed:
                failed = int(m_failed.group(1))
            if m_errors:
                errors = int(m_errors.group(1))
            if m_passed or m_failed or m_errors:
                break

    return {
        "passed": passed,
        "failed": failed,
        "errors": errors,
        "total": passed + failed + errors,
    }


async def _run_pytest(project_dir: str) -> dict:
    """Run pytest and return parsed results."""
    proc = await asyncio.create_subprocess_exec(
        "uv", "run", "pytest", "tests/", "-v", "--ignore=tests/integration",
        "--tb=short", "-q",
        cwd=project_dir,
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.STDOUT,
    )
    stdout, _ = await proc.communicate()
    output = stdout.decode("utf-8", errors="replace") if stdout else ""
    result = parse_pytest_output(output)
    result["returncode"] = proc.returncode
    return result


async def build_round_summary(
    pool: asyncpg.Pool,
    project_id: str,
    project_dir: str,
    run_tests: bool = True,
) -> dict:
    """Execute the post-round checklist and return a combined summary.

    Steps:
    1. Run pytest (if run_tests=True)
    2. Get project status snapshot
    3. Return combined dict with checklist status
    """
    from loom.graph.project import get_project_status

    checklist: list[dict] = []

    # Step 1: Run tests
    test_result = None
    if run_tests:
        try:
            test_result = await _run_pytest(project_dir)
            status = "pass" if test_result["returncode"] == 0 else "fail"
            checklist.append({"step": "Run tests", "status": status})
        except Exception as exc:
            logger.warning("Failed to run tests: %s", exc)
            checklist.append({"step": "Run tests", "status": "error"})
    else:
        checklist.append({"step": "Run tests", "status": "skipped"})

    # Step 2: Project snapshot
    project_status = None
    try:
        ps = await get_project_status(pool, project_id)
        project_status = ps.model_dump(mode="json")
        checklist.append({"step": "Project snapshot", "status": "done"})
    except Exception as exc:
        logger.warning("Failed to get project status: %s", exc)
        checklist.append({"step": "Project snapshot", "status": "error"})

    return {
        "tests": test_result,
        "project": project_status,
        "checklist": checklist,
    }
