"""Configuration and language mappings."""

from __future__ import annotations

from dataclasses import dataclass, field
from pathlib import Path

# ── Language registry ──────────────────────────────────────────────────────────

LANGUAGE_MAP: dict[str, str] = {
    # extension → language key
    ".py": "python",
    ".pyw": "python",
    ".js": "javascript",
    ".mjs": "javascript",
    ".cjs": "javascript",
    ".jsx": "javascript",
    ".ts": "typescript",
    ".tsx": "typescript",
    ".java": "java",
    ".go": "go",
    ".rs": "rust",
    ".c": "c",
    ".h": "c",
    ".cpp": "cpp",
    ".cxx": "cpp",
    ".cc": "cpp",
    ".hpp": "cpp",
    ".hxx": "cpp",
    ".rb": "ruby",
    ".erb": "ruby",
    ".cs": "csharp",
    ".swift": "swift",
    ".kt": "kotlin",
    ".kts": "kotlin",
    ".php": "php",
    ".scala": "scala",
    ".lua": "lua",
    ".r": "r",
    ".R": "r",
    ".dart": "dart",
    ".ex": "elixir",
    ".exs": "elixir",
}

# Tree-sitter grammar package names (pip installable)
TREE_SITTER_GRAMMARS: dict[str, str] = {
    "python": "tree_sitter_python",
    "javascript": "tree_sitter_javascript",
    "typescript": "tree_sitter_typescript",
    "java": "tree_sitter_java",
    "go": "tree_sitter_go",
    "rust": "tree_sitter_rust",
    "c": "tree_sitter_c",
    "cpp": "tree_sitter_cpp",
    "ruby": "tree_sitter_ruby",
}

# Directories to always skip
SKIP_DIRS: set[str] = {
    "node_modules", ".git", ".svn", ".hg", "__pycache__", ".mypy_cache",
    ".pytest_cache", ".tox", ".venv", "venv", "env", ".env", "dist", "build",
    ".next", ".nuxt", "target", "bin", "obj", ".idea", ".vscode",
    "vendor", "Pods", ".gradle", ".settings", "coverage", ".nyc_output",
    ".cache", "tmp", "temp",
}

# Files to always skip
SKIP_FILES: set[str] = {
    "package-lock.json", "yarn.lock", "pnpm-lock.yaml", "Cargo.lock",
    "poetry.lock", "Gemfile.lock", "composer.lock", "go.sum",
}

# Max file size to parse (500 KB)
MAX_FILE_SIZE: int = 512_000


@dataclass
class HLDConfig:
    """Runtime configuration for the HLD generator."""

    # Target path (file or directory)
    target: Path = field(default_factory=lambda: Path("."))

    # LLM provider (built-in: anthropic, openai, none; or plugin-registered name)
    llm_provider: str = "anthropic"
    llm_model: str = ""
    api_key: str = field(default="", repr=False)

    # Output
    output_dir: Path = field(default_factory=lambda: Path("./hld_output"))

    # Scanning
    max_file_size: int = MAX_FILE_SIZE
    include_tests: bool = False
    max_files: int = 500

    # LLM context
    max_tokens_per_chunk: int = 12_000

    # Diagram
    max_diagram_edges: int = 60

    def __post_init__(self) -> None:
        if self.max_files <= 0:
            raise ValueError(f"max_files must be positive, got {self.max_files}")
        if self.max_file_size <= 0:
            raise ValueError(f"max_file_size must be positive, got {self.max_file_size}")
        if self.max_tokens_per_chunk <= 0:
            raise ValueError(f"max_tokens_per_chunk must be positive, got {self.max_tokens_per_chunk}")
        if self.max_diagram_edges < 0:
            raise ValueError(f"max_diagram_edges must be non-negative, got {self.max_diagram_edges}")

        if not self.llm_model:
            self.llm_model = {
                "anthropic": "claude-sonnet-4-20250514",
                "openai": "gpt-4o",
                "none": "",
            }.get(self.llm_provider, "")
