"""pip/Python ecosystem parser — requirements.txt, Pipfile, pyproject.toml."""

from __future__ import annotations

import re
from pathlib import Path
from typing import Any


def parse(repo_path: Path) -> dict[str, Any]:
    sources: list[str] = []
    deps: list[dict[str, Any]] = []

    req_file = repo_path / "requirements.txt"
    if req_file.exists():
        sources.append("requirements.txt")
        deps.extend(_parse_requirements(req_file))

    pp = repo_path / "pyproject.toml"
    if pp.exists():
        sources.append("pyproject.toml")
        deps.extend(_parse_pyproject(pp))

    pipfile = repo_path / "Pipfile"
    if pipfile.exists():
        sources.append("Pipfile")
        deps.extend(_parse_pipfile(pipfile))

    if not sources:
        return {"found": False, "ecosystem": "pip"}

    has_lockfile = any(
        (repo_path / lf).exists()
        for lf in ["Pipfile.lock", "uv.lock", "poetry.lock"]
    ) or (req_file.exists() and _requirements_are_pinned(req_file))

    return {
        "found": True,
        "ecosystem": "pip",
        "manifest_files": sources,
        "has_lockfile": has_lockfile,
        "packages": deps,
    }


def _parse_requirements(path: Path) -> list[dict[str, Any]]:
    deps = []
    for line in path.read_text().splitlines():
        line = line.strip()
        if not line or line.startswith("#") or line.startswith("-"):
            continue
        m = re.match(r"^([A-Za-z0-9_\-\[\].]+)\s*([>=<!~^,\s\d.*]+)?", line)
        if m:
            name = m.group(1).split("[")[0]
            ver_spec = (m.group(2) or "").strip()
            deps.append({
                "name": name,
                "version_spec": ver_spec,
                "resolved_version": _extract_pinned_version(ver_spec),
                "is_direct": True,
                "ecosystem": "pip",
            })
    return deps


def _parse_pyproject(path: Path) -> list[dict[str, Any]]:
    try:
        import toml
        data = toml.loads(path.read_text())
    except Exception:  # noqa: BLE001
        return []
    deps = []
    for dep in data.get("project", {}).get("dependencies", []):
        m = re.match(r"^([A-Za-z0-9_\-\[\].]+)", str(dep))
        if m:
            deps.append({
                "name": m.group(1),
                "version_spec": dep,
                "resolved_version": "",
                "is_direct": True,
                "ecosystem": "pip",
            })
    return deps


def _parse_pipfile(path: Path) -> list[dict[str, Any]]:
    try:
        import toml
        data = toml.loads(path.read_text())
    except Exception:  # noqa: BLE001
        return []
    deps = []
    for section in ("packages", "dev-packages"):
        for name, ver in data.get(section, {}).items():
            ver_str = str(ver) if isinstance(ver, str) else ""
            deps.append({
                "name": name,
                "version_spec": ver_str,
                "resolved_version": _extract_pinned_version(ver_str),
                "is_direct": True,
                "ecosystem": "pip",
            })
    return deps


def _extract_pinned_version(ver_spec: str) -> str:
    m = re.search(r"==\s*([\d.]+)", ver_spec)
    return m.group(1) if m else ""


def _requirements_are_pinned(path: Path) -> bool:
    """Heuristic: requirements.txt is 'pinned' if most lines use ==."""
    lines = [ln.strip() for ln in path.read_text().splitlines()
             if ln.strip() and not ln.strip().startswith("#")]
    if not lines:
        return False
    pinned = sum(1 for ln in lines if "==" in ln)
    return pinned / len(lines) >= 0.8
