"""Stdout-based parsing: test failure extraction from pytest output."""

from __future__ import annotations

import re

TEST_HEADER_RE = re.compile(r"_{3,}\s*(.*?)\s*_{3,}$")

_MIN_EQUALS_FOR_SECTION = 3


def parse_test_failures_from_stdout(
    stdout: str,
) -> dict[str, str]:
    """Extract individual pytest test failures by name."""
    lines = stdout.splitlines()
    start = _find_failures_start(lines)
    if start is None:
        return {}
    end = _find_failures_end(lines, start)
    return _collect_failures(lines[start:end])


def _find_failures_start(
    lines: list[str],
) -> int | None:
    """Find the index of the FAILURES header."""
    for i, line in enumerate(lines):
        if "= FAILURES =" in line:
            return i
    return None


def _find_failures_end(
    lines: list[str],
    start: int,
) -> int:
    """Find the end index of the failures section."""
    for j in range(start + 1, len(lines)):
        stripped = lines[j].strip()
        if "short test summary info" in stripped:
            return j
        if (
            stripped.startswith("=")
            and stripped.count("=") > _MIN_EQUALS_FOR_SECTION
        ):
            return j
    return len(lines)


def _collect_failures(
    failure_block: list[str],
) -> dict[str, str]:
    """Collect test failures from a block of lines."""
    failures: dict[str, str] = {}
    current_name: str | None = None
    current_lines: list[str] = []

    for line in failure_block:
        m = TEST_HEADER_RE.match(line.strip())
        if m:
            if current_name is not None:
                failures[current_name] = "".join(
                    current_lines,
                )
            current_name = m.group(1)
            current_lines = []
        elif current_name:
            current_lines.append(line + "\n")

    if current_name:
        failures[current_name] = "".join(current_lines)

    return failures
