"""Requirements.txt / pyproject.toml dependency parser."""
from __future__ import annotations

import re
from pathlib import Path

from packaging.requirements import Requirement
from packaging.version import Version


def parse_requirements_txt(path: Path) -> list[tuple[str, str]]:
    """
    Parse a requirements.txt file and return ``[(name, version), ...]``.
    Lines without a pinned version (``==``) are returned with version ``"latest"``.
    Skips comments, blank lines, and ``-r`` / ``-c`` directives.
    """
    results: list[tuple[str, str]] = []
    for raw_line in path.read_text(encoding="utf-8").splitlines():
        line = raw_line.strip()
        if not line or line.startswith("#") or line.startswith("-"):
            continue
        # Strip inline comments
        line = line.split("#", 1)[0].strip()
        if not line:
            continue
        try:
            req = Requirement(line)
        except Exception:  # noqa: BLE001
            continue
        name = req.name
        version = _extract_pinned_version(req)
        results.append((name, version))
    return results


def parse_pyproject_toml(path: Path) -> list[tuple[str, str]]:
    """
    Extract dependencies from a ``pyproject.toml`` (PEP 621 ``[project]`` section).
    Returns ``[(name, version), ...]``.
    """
    try:
        import tomllib  # Python 3.11+
    except ImportError:
        try:
            import tomli as tomllib  # type: ignore[no-redef]
        except ImportError:
            return []

    data: dict = tomllib.loads(path.read_text(encoding="utf-8"))  # type: ignore[assignment]
    deps: list[str] = data.get("project", {}).get("dependencies", [])
    results: list[tuple[str, str]] = []
    for dep in deps:
        try:
            req = Requirement(dep)
            results.append((req.name, _extract_pinned_version(req)))
        except Exception:  # noqa: BLE001
            continue
    return results


def _extract_pinned_version(req: Requirement) -> str:
    """Return the exact pinned version (``==X.Y.Z``) or ``"latest"``."""
    for spec in req.specifier:
        if spec.operator == "==":
            return spec.version
    return "latest"


def discover_requirements(project_root: Path) -> list[tuple[str, str]]:
    """
    Auto-discover dependency files under *project_root* and return a merged,
    deduplicated list of ``(name, version)`` tuples.
    """
    found: dict[str, str] = {}  # name -> version (last-write wins)
    candidates = [
        *project_root.glob("requirements*.txt"),
        *project_root.glob("requirements/*.txt"),
    ]
    for req_file in sorted(candidates):
        for name, version in parse_requirements_txt(req_file):
            found[name.lower()] = version

    pyproject = project_root / "pyproject.toml"
    if pyproject.exists():
        for name, version in parse_pyproject_toml(pyproject):
            found.setdefault(name.lower(), version)

    return list(found.items())
