"""Base parser interface for dead code detection."""

from __future__ import annotations

from dataclasses import dataclass
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Callable

if TYPE_CHECKING:
    from tree_sitter import Node


@dataclass
class SymbolDefinition:
    name: str
    line: int
    definition_type: str
    exported: bool = False


@dataclass
class ImportedSymbol:
    name: str
    line: int
    imported_from: str | None = None
    alias: str | None = None


@dataclass
class VariableDefinition:
    name: str
    line: int
    scope_type: str
    definition_type: str


@dataclass
class SymbolReference:
    name: str
    line: int


class DeadCodeParser(ABC):
    def __init__(self) -> None:
        self._reference_extractor: (
            Callable[[Node, str], list[SymbolReference]] | None
        ) = None

    @abstractmethod
    def extract_imports(self, root: Node, source: str) -> list[ImportedSymbol]:
        pass

    @abstractmethod
    def extract_definitions(self, root: Node, source: str) -> list[SymbolDefinition]:
        pass

    def extract_references(self, root: Node, source: str) -> list[SymbolReference]:
        if self._reference_extractor is None:
            self._reference_extractor = self._create_reference_extractor()
        return self._reference_extractor(root, source)

    def _create_reference_extractor(
        self,
    ) -> Callable[[Node, str], list[SymbolReference]]:
        from vibelexity.patterns.common import create_query, run_captures

        query_str = "(identifier) @usage_ref"

        def extractor(root: Node, source: str) -> list[SymbolReference]:
            query = create_query(self._get_language(), query_str)
            captures = run_captures(query, root)
            refs = []
            for node, capture_name in captures:
                if capture_name == "usage_ref" and node.text:
                    refs.append(
                        SymbolReference(node.text.decode(), node.start_point[0] + 1)
                    )
            return refs

        return extractor

    def _get_language(self):
        raise NotImplementedError("Subclasses must implement _get_language()")
