"""Go dead code parser."""

from __future__ import annotations

from tree_sitter import Node

from vibelexity.parsers.go import GO_LANGUAGE
from vibelexity.patterns.common import create_query, run_captures
from vibelexity.dead_code.parsers.base import (
    SymbolDefinition,
    ImportedSymbol,
    DeadCodeParser,
)


class GoDeadCodeParser(DeadCodeParser):
    def _get_language(self):
        return GO_LANGUAGE

    def extract_imports(self, root, source):
        query = create_query(GO_LANGUAGE, "(import_declaration) @import_decl")
        captures = run_captures(query, root)
        imports = []
        for decl_node, _ in captures:
            self._process_import_declaration(decl_node, imports)
        return imports

    def _process_import_declaration(self, decl_node, imports):
        for child in decl_node.children:
            if child.type == "import_spec_list":
                self._process_import_spec_list(child, imports)
                return
            elif child.type == "import_spec":
                self._process_import_spec(child, imports)
                return

    def _process_import_spec_list(self, list_node, imports):
        for child in list_node.children:
            if child.type == "import_spec":
                self._process_import_spec(child, imports)

    def _process_import_spec(self, spec_node, imports):
        path = None
        has_blank_identifier = False
        has_dot_import = False
        for child in spec_node.children:
            if child.type == "blank_identifier":
                has_blank_identifier = True
            elif child.type == "dot":
                has_dot_import = True
            elif child.type == "interpreted_string_literal":
                path = child.text.decode().strip('"')
        if has_blank_identifier or has_dot_import:
            return
        pkg_name = (
            path.split("/")[-1] if path and "/" in path else (path if path else "")
        )
        if pkg_name and path:
            imports.append(
                ImportedSymbol(
                    name=pkg_name,
                    line=spec_node.start_point[0] + 1,
                    imported_from=path,
                    alias=None,
                )
            )

    def _get_method_receiver_type(self, method_decl):
        """Extract receiver type from method declaration."""
        if not method_decl or method_decl.child_count < 2:
            return ""
        param_list = method_decl.children[1]
        if not param_list or param_list.type != "parameter_list":
            return ""
        for child in param_list.children:
            if child.type == "parameter_declaration":
                identifiers = [
                    c
                    for c in child.children
                    if c.type in ("identifier", "type_identifier")
                ]
                if len(identifiers) >= 2 and identifiers[1].text:
                    return identifiers[1].text.decode()
        return ""

    def _extract_function_declarations(self, root):
        """Extract function definitions from AST."""
        defs = []
        query_str = "(function_declaration name: (identifier) @func_name)"
        try:
            query = create_query(GO_LANGUAGE, query_str)
            captures = run_captures(query, root)
            for node, name in captures:
                if name == "func_name" and node.text:
                    func_name = node.text.decode()
                    is_exported = bool(func_name) and func_name[0].isupper()
                    defs.append(
                        SymbolDefinition(
                            func_name, node.start_point[0] + 1, "function", is_exported
                        )
                    )
        except Exception:
            pass
        return defs

    def _extract_method_declarations(self, root):
        """Extract method definitions from AST."""
        defs = []
        query_str = "(method_declaration name: (field_identifier) @method_name)"
        try:
            query = create_query(GO_LANGUAGE, query_str)
            captures = run_captures(query, root)
            for node, name in captures:
                if name == "method_name" and node.text:
                    method_decl = node.parent
                    receiver_type = self._get_method_receiver_type(method_decl)
                    prefix = f"{receiver_type}." if receiver_type else ""
                    full_name = f"{prefix}{node.text.decode()}"
                    method_name = node.text.decode()
                    is_exported = bool(method_name) and method_name[0].isupper()
                    defs.append(
                        SymbolDefinition(
                            full_name, node.start_point[0] + 1, "function", is_exported
                        )
                    )
        except Exception:
            pass
        return defs

    def extract_definitions(self, root, source):
        defs = self._extract_function_declarations(root)
        defs.extend(self._extract_method_declarations(root))
        return defs

    def extract_abstract_info(self, root, source):
        return set(), set()

    def is_exported(self, name):
        return bool(name) and name[0].isupper()
