from __future__ import annotations

from typing import TYPE_CHECKING

import tree_sitter_typescript as tstypescript
from tree_sitter import Language

from vibelexity.circular_deps.models import ImportInfo
from vibelexity.circular_deps.parsers.base import ImportParser
from vibelexity.parsers.shared import parse_with_language

if TYPE_CHECKING:
    from tree_sitter import Node

TS_LANGUAGE = Language(tstypescript.language_typescript())
TSX_LANGUAGE = Language(tstypescript.language_tsx())
_IMPORT_NODE_TYPES = {"import_statement", "export_statement"}


def parse(code: str, tsx: bool = False) -> Node:
    lang = TSX_LANGUAGE if tsx else TS_LANGUAGE
    return parse_with_language(lang, code)


class TypeScriptImportParser(ImportParser):
    def extract_imports(self, source: str, filepath: str) -> list[ImportInfo]:
        tsx = filepath.endswith(".tsx") or filepath.endswith(".jsx")
        root = parse(source, tsx=tsx)
        imports: list[ImportInfo] = []

        for node in root.children:
            if node.type in _IMPORT_NODE_TYPES:
                imports.extend(self._process_import_export_statement(node))

        return self._filter_dynamic(imports, root)

    def _process_import_export_statement(self, node: Node) -> list[ImportInfo]:
        imports: list[ImportInfo] = []

        for child in node.children:
            if child.type == "string":
                text = child.text.decode() if child.text else ""
                module = text.strip("\"'")
                if module:
                    imports.append(
                        ImportInfo(
                            raw_module=module,
                            resolved_path=None,
                            import_type=self._detect_import_type(module),
                            line=node.start_point[0] + 1,
                            is_dynamic=False,
                            node_type=node.type,
                        )
                    )

        return imports

    def _detect_import_type(self, module: str) -> str:
        if module.startswith(".") or module.startswith(".."):
            return "relative"
        return "absolute"

    def _filter_dynamic(
        self, imports: list[ImportInfo], root: Node
    ) -> list[ImportInfo]:
        for node in root.children:
            if node.type == "expression_statement":
                for expr in node.children:
                    if expr.type == "call":
                        if self._is_dynamic_import_call(expr):
                            line = node.start_point[0] + 1
                            for imp in imports:
                                if imp.line == line:
                                    imp.is_dynamic = True

        return [imp for imp in imports if not imp.is_dynamic]

    def _is_dynamic_import_call(self, call_node: Node) -> bool:
        for child in call_node.children:
            if child.type == "import":
                return True
            for gc in child.children:
                if gc.type == "import":
                    return True
        return False
