"""
Parser manager — picks the best parser for each file:
  1. Plugin-registered parser (highest priority)
  2. Tree-sitter parser
  3. Regex fallback parser
"""

from __future__ import annotations

import logging
import os
import threading
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path

from hld_generator.parsers.base import ParsedFile
from hld_generator.parsers.tree_sitter_parser import TreeSitterParser
from hld_generator.parsers.regex_parser import RegexParser
from hld_generator.scanner import ScannedFile

logger = logging.getLogger(__name__)


class ParserManager:
    """Facade that delegates to the best available parser backend."""

    def __init__(self) -> None:
        self._ts = TreeSitterParser()
        self._regex = RegexParser()
        # Per-language tree-sitter availability: None = untried, True/False = result
        self._ts_status: dict[str, bool] = {}
        self._ts_lock = threading.Lock()

    def parse(self, scanned: ScannedFile) -> ParsedFile:
        """Parse a scanned file, auto-selecting the best backend."""
        from hld_generator.plugins import registry

        path = Path(scanned.path)
        lang = scanned.language
        # Use relative_path as the module ID for cleaner output
        rel_path = scanned.relative_path

        # Priority 1: plugin-registered parser
        plugin_parser = registry.get_parser(lang)
        if plugin_parser is not None:
            try:
                result = plugin_parser.parse_file(path, lang)
                if not result.errors:
                    result.file_path = rel_path
                    return result
                logger.debug("Plugin parser errors for %s, falling back", path)
            except Exception as exc:
                logger.debug("Plugin parser failed for %s: %s", path, exc)

        # Priority 2: tree-sitter (per-language thread-safe check)
        with self._ts_lock:
            ts_ok = self._ts_status.get(lang)
        if ts_ok is not False and self._ts.supports(lang):
            try:
                result = self._ts.parse_file(path, lang)
                if not result.errors:
                    with self._ts_lock:
                        self._ts_status[lang] = True
                    result.file_path = rel_path
                    return result
                logger.debug(
                    "Tree-sitter errors for %s, falling back to regex", path
                )
            except Exception as exc:
                logger.debug("Tree-sitter failed for %s: %s", path, exc)
                with self._ts_lock:
                    if lang not in self._ts_status:
                        logger.info(
                            "Tree-sitter not working for %s — using regex parser", lang
                        )
                        self._ts_status[lang] = False

        # Priority 3: regex fallback
        result = self._regex.parse_file(path, lang)
        result.file_path = rel_path
        return result

    def parse_all(self, files: list[ScannedFile]) -> list[ParsedFile]:
        """Parse all files, using thread parallelism for I/O-bound parsing."""
        if len(files) <= 1:
            return [self.parse(f) for f in files]

        max_workers = min(os.cpu_count() or 4, len(files))
        with ThreadPoolExecutor(max_workers=max_workers) as executor:
            results = list(executor.map(self.parse, files))
        return results
