"""Runs the project's own configured test command and turns it into a StageTestReport."""

from __future__ import annotations

import re
import shlex
from pathlib import Path

from .domain import TaskRecord, StageTestReport
from .infra.process import ProcessRunner
from .policy import CommandNotAllowed, CommandPolicy

#: ponytail: regex over the tail of stdout. Fine for pytest/jest/cargo; swap for a
#: junit-xml reader if a project needs exact per-test attribution.
FAILED_COUNT = re.compile(r"(\d+)\s+failed", re.IGNORECASE)

#: The runner's own tally line, kept verbatim so a reviewer reads the tool, not our paraphrase.
SUMMARY_LINE = re.compile(
    r"^.*?\b\d+\s+(?:passed|failed|error|ok|tests?)\b.*$", re.IGNORECASE | re.MULTILINE
)


class CommandTestRunner:
    def __init__(self, policy: CommandPolicy, log_root: str | Path, command_name: str = "test", allow_network: bool = False) -> None:
        self.policy = policy
        self.log_root = Path(log_root)
        self.command_name = command_name
        self.allow_network = allow_network

    def __call__(self, task: TaskRecord, worktree: Path) -> StageTestReport:
        try:
            command = self.policy.command_for(self.command_name)
        except CommandNotAllowed as error:
            return self._unconfigured(error)
        result = ProcessRunner(self.log_root, allow_network=self.allow_network).run(
            shlex.split(command), worktree, task.limits.command_timeout_s, name=f"command-{task.task_id[:8]}-{task.cycle:02d}"
        )
        text = _tail(result.stdout_path) + _tail(result.stderr_path)
        match = FAILED_COUNT.search(text)
        found = SUMMARY_LINE.findall(text)
        return StageTestReport(
            command=command,
            exit_code=result.exit_code,
            duration_ms=result.duration_ms,
            stdout_path=str(result.stdout_path),
            stderr_path=str(result.stderr_path),
            passed=result.status == "SUCCESS",
            summary=(found[-1].strip()[:300] if found else ""),
            failed=int(match.group(1)) if match else (0 if result.status == "SUCCESS" else None),
        )

    @staticmethod
    def _unconfigured(error: Exception) -> StageTestReport:
        """No configured test command is a hard stop, never a silent pass."""
        return StageTestReport(
            command=str(error),
            exit_code=None,
            duration_ms=0,
            stdout_path="",
            stderr_path="",
            passed=False,
            failed=None,
        )


def _tail(path: Path, limit: int = 8000) -> str:
    try:
        return path.read_text(encoding="utf-8", errors="replace")[-limit:]
    except OSError:
        return ""
