"""Project enrichment helpers — detect stack, frameworks, and git info."""
from __future__ import annotations

import json
from pathlib import Path
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from proxym.projects import Project

# ── Marker → (language, framework) lookup ────────────────────
_FILE_MARKERS: dict[str, tuple[str | None, str | None]] = {
    "pyproject.toml": ("python", None),
    "setup.py": ("python", None),
    "requirements.txt": ("python", None),
    "package.json": ("javascript", None),
    "tsconfig.json": ("typescript", None),
    "Cargo.toml": ("rust", None),
    "go.mod": ("go", None),
    "pom.xml": ("java", "maven"),
    "build.gradle": ("java", "gradle"),
    "Gemfile": ("ruby", "rails"),
    "mix.exs": ("elixir", "phoenix"),
    "docker-compose.yml": (None, "docker"),
    "Dockerfile": (None, "docker"),
}

_NPM_FRAMEWORK_KEYS: dict[str, str] = {
    "react": "react",
    "vue": "vue",
    "next": "nextjs",
    "fastify": "fastify",
    "express": "express",
}

_PYTHON_FRAMEWORK_KEYWORDS: dict[str, str] = {
    "fastapi": "fastapi",
    "django": "django",
    "flask": "flask",
}


def detect_toolchain(path: Path) -> tuple[list[str], list[str]]:
    """Return (stack, frameworks) detected from file markers at *path*."""
    stack: list[str] = []
    frameworks: list[str] = []
    for filename, (lang, fw) in _FILE_MARKERS.items():
        if (path / filename).exists():
            if lang and lang not in stack:
                stack.append(lang)
            if fw and fw not in frameworks:
                frameworks.append(fw)
    return stack, frameworks


def enrich_npm_frameworks(path: Path, frameworks: list[str]) -> list[str]:
    """Append JS/TS frameworks detected from package.json dependencies."""
    pkg_path = path / "package.json"
    if not pkg_path.exists():
        return frameworks
    try:
        pkg = json.loads(pkg_path.read_text())
        deps = {**pkg.get("dependencies", {}), **pkg.get("devDependencies", {})}
        for key, fw_name in _NPM_FRAMEWORK_KEYS.items():
            if key in deps and fw_name not in frameworks:
                frameworks.append(fw_name)
    except Exception:
        pass
    return frameworks


def enrich_python_frameworks(path: Path, frameworks: list[str]) -> list[str]:
    """Append Python frameworks detected from pyproject.toml content."""
    toml_path = path / "pyproject.toml"
    if not toml_path.exists():
        return frameworks
    try:
        text = toml_path.read_text().lower()
        for keyword, fw_name in _PYTHON_FRAMEWORK_KEYWORDS.items():
            if keyword in text and fw_name not in frameworks:
                frameworks.append(fw_name)
    except Exception:
        pass
    return frameworks


def enrich_git_info(path: Path) -> bool:
    """Return True if the path contains a .git directory."""
    return (path / ".git").exists()


def enrich_local_project(project: Project) -> Project:
    """Enrich a local project with auto-detected metadata.

    Orchestrates git detection, toolchain scanning, and framework sniffing.
    """
    path = Path(project.local_path or project.source_path)
    if not path.exists():
        return project

    project.has_git = enrich_git_info(path)

    stack, frameworks = detect_toolchain(path)
    frameworks = enrich_npm_frameworks(path, frameworks)
    frameworks = enrich_python_frameworks(path, frameworks)

    project.stack = stack
    project.frameworks = frameworks
    return project
