"""npm ecosystem parser — package.json + package-lock.json."""

from __future__ import annotations

import json
import re
from pathlib import Path
from typing import Any


def parse(repo_path: Path) -> dict[str, Any]:
    pkg_json = repo_path / "package.json"
    lock_json = repo_path / "package-lock.json"

    if not pkg_json.exists():
        return {"found": False, "ecosystem": "npm"}

    try:
        pkg = json.loads(pkg_json.read_text())
    except Exception:  # noqa: BLE001
        return {"found": False, "ecosystem": "npm", "error": "Failed to parse package.json"}

    deps: list[dict[str, Any]] = []
    for name, ver in {
        **pkg.get("dependencies", {}),
        **pkg.get("devDependencies", {}),
    }.items():
        deps.append({
            "name": name,
            "version_spec": str(ver),
            "resolved_version": _clean_version(str(ver)),
            "is_direct": True,
            "ecosystem": "npm",
        })

    has_lockfile = lock_json.exists()
    if has_lockfile:
        try:
            lock = json.loads(lock_json.read_text())
            packages = lock.get("packages", lock.get("dependencies", {}))
            for pkg_path, info in packages.items():
                if not pkg_path or pkg_path == "":
                    continue
                pkg_name = pkg_path.replace("node_modules/", "").lstrip("/")
                resolved_ver = info.get("version", "")
                if resolved_ver and not any(d["name"] == pkg_name for d in deps):
                    deps.append({
                        "name": pkg_name,
                        "version_spec": resolved_ver,
                        "resolved_version": resolved_ver,
                        "is_direct": False,
                        "ecosystem": "npm",
                    })
        except Exception:  # noqa: BLE001
            pass

    return {
        "found": True,
        "ecosystem": "npm",
        "manifest_file": "package.json",
        "has_lockfile": has_lockfile,
        "lockfile": "package-lock.json",
        "packages": deps,
    }


def _clean_version(ver: str) -> str:
    cleaned = re.sub(r"^[\^~>=<*\s]+", "", ver.strip())
    if " " in cleaned:
        cleaned = cleaned.split()[0]
    return cleaned or ver
