"""Test runner for GuardRail."""

import subprocess
import sys
from pathlib import Path
from typing import List, Optional, Tuple


class TestRunner:
    """Runs pytest tests and reports results."""

    def __init__(self, test_dir: Path, root: Path):
        """
        Initialize test runner.

        Args:
            test_dir: Directory containing generated tests.
            root: Project root directory.
        """
        self.test_dir = Path(test_dir)
        self.root = Path(root)

    def run_tests(self) -> Tuple[bool, str, Optional[str]]:
        """
        Run pytest on generated tests.

        Returns:
            Tuple of (passed: bool, output: str, error_output: Optional[str])
        """
        if not self.test_dir.exists():
            return True, "No test directory found.", None
            
        test_files = list(self.test_dir.glob("test_*.py"))
        if not test_files:
            return True, "No tests to run.", None

        try:
            # Run pytest on the test directory
            result = subprocess.run(
                [
                    sys.executable,
                    "-m",
                    "pytest",
                    str(self.test_dir),
                    "-v",
                    "--tb=short",
                    "-q",  # Quiet mode
                ],
                cwd=self.root,
                capture_output=True,
                text=True,
                timeout=300,  # 5 minute timeout
            )

            passed = result.returncode == 0
            return passed, result.stdout, result.stderr

        except subprocess.TimeoutExpired:
            return False, "", "Test execution timed out after 5 minutes."
        except FileNotFoundError:
            return False, "", "pytest not found. Install pytest to run tests."
        except Exception as e:
            return False, "", f"Error running tests: {e}"

    def get_failing_tests(self, output: str) -> List[str]:
        """
        Extract failing test names from pytest output.

        Args:
            output: Pytest output string.

        Returns:
            List of failing test names.
        """
        failing_tests = []
        lines = output.split("\n")

        for line in lines:
            # Look for lines like "FAILED test_file.py::test_function"
            if "FAILED" in line:
                # Extract test name
                parts = line.split()
                for part in parts:
                    if "::" in part:
                        failing_tests.append(part)
                        break

        return failing_tests

