import logging
import os
import shutil
import subprocess
import tempfile
from typing import Any

from py_agent.infrastructure import xml_parser

logger = logging.getLogger(__name__)


def get_pytest_command(repository_root_path: str) -> list[str] | None:
    venv_folder_names = [".venv", "venv", "env"]
    is_windows = os.name == "nt"
    scripts_folder = "Scripts" if is_windows else "bin"
    python_executable = "python.exe" if is_windows else "python"

    for folder_name in venv_folder_names:
        local_python_path = os.path.join(
            repository_root_path, folder_name, scripts_folder, python_executable
        )
        if os.path.exists(local_python_path):
            check = subprocess.run(
                [local_python_path, "-c", "import pytest"],
                capture_output=True,
            )
            if check.returncode == 0:
                return [local_python_path, "-m", "pytest"]
            logger.info(f"Skipping {local_python_path} — pytest not installed")

    global_pytest_path = shutil.which("pytest")
    if not global_pytest_path:
        logger.error("No pytest found")
        return None

    return [global_pytest_path]


def run_pytest(
    test_file_path: str,
    repository_root_path: str,
    extra_pythonpath: list[str] | None = None,
) -> dict[str, Any]:
    with tempfile.NamedTemporaryFile(delete=False, suffix=".xml") as temp_file:
        temp_file_path = temp_file.name

    if not temp_file_path:
        raise RuntimeError("Could not create a temporary file")

    command = get_pytest_command(repository_root_path)
    if not command:
        raise RuntimeError("Unable to locate pytest")

    command.extend(
        [
            f"--junitxml={temp_file_path}",
            "--disable-warnings",
            test_file_path,
        ]
    )

    logger.info(f"pytest validate command: {' '.join(command)}")
    env = None
    if extra_pythonpath:
        env = os.environ.copy()
        extra = os.pathsep.join(os.path.join(repository_root_path, p) for p in extra_pythonpath)
        env["PYTHONPATH"] = extra + os.pathsep + env.get("PYTHONPATH", "")
    result = subprocess.run(
        command, cwd=repository_root_path, capture_output=True, text=True, env=env
    )

    if result.stdout:
        print(result.stdout)
    if result.stderr:
        print(result.stderr)

    pytest_report = xml_parser.parse(temp_file_path, result.returncode) if temp_file_path else None
    if pytest_report is None and temp_file_path:
        logger.error(
            f"pytest produced no JUnit XML (exit code {result.returncode}). "
            f"stdout: {result.stdout[:500] if result.stdout else '(empty)'} | "
            f"stderr: {result.stderr[:500] if result.stderr else '(empty)'}"
        )

    if pytest_report is not None:
        summary = pytest_report.get("summary", {})
        passed = summary.get("passed", 0)
        failed = summary.get("failed", 0)
        logger.info(f"pytest results: {passed} passed, {failed} failed")

    if os.path.exists(temp_file_path):
        os.remove(temp_file_path)

    return {
        "stdout": result.stdout,
        "stderr": result.stderr,
        "pytestReport": pytest_report,
        "command": " ".join(command),
    }
