"""Go tree-sitter parser and function collection."""

from __future__ import annotations

import tree_sitter_go as tsgo
from tree_sitter import Language, Node

from vibelexity.metrics.fatness.go import param_count
from vibelexity.parsers.shared import (
    collect_functions_wrapper,
    func_param_count_wrapper,
    parse_with_language,
)

GO_LANGUAGE = Language(tsgo.language())

parse = lambda code: parse_with_language(GO_LANGUAGE, code)


def _collect_functions_recursive(node: Node, acc: list[Node]) -> None:
    if node.type in ("function_declaration", "method_declaration"):
        acc.append(node)
    elif node.type == "func_literal":
        if is_named_func_literal(node):
            acc.append(node)
    for child in node.children:
        _collect_functions_recursive(child, acc)


def is_named_func_literal(node: Node) -> bool:
    """Check if a func_literal is assigned to a variable (named closure).

    Matches patterns like:
        f := func() {}       (short_var_declaration)
        var f = func() {}    (var_spec)
    """
    if node.type != "func_literal":
        return False
    parent = node.parent
    if parent is None:
        return False
    if (
        parent.type == "expression_list"
        and parent.parent
        and parent.parent.type == "short_var_declaration"
    ):
        return True
    if parent.type == "var_spec":
        return True
    return False


def func_name(node: Node) -> str:
    """Extract function name from a function node."""
    if node.type in ("function_declaration", "method_declaration"):
        name_node = node.child_by_field_name("name")
        if name_node:
            return name_node.text.decode()
        return "<anonymous>"
    if node.type == "func_literal":
        parent = node.parent
        if parent is None:
            return "<anonymous>"
        if (
            parent.type == "expression_list"
            and parent.parent
            and parent.parent.type == "short_var_declaration"
        ):
            svd = parent.parent
            left = svd.child_by_field_name("left")
            if left:
                for child in left.children:
                    if child.type == "identifier":
                        return child.text.decode()
        if parent.type == "var_spec":
            name_node = parent.child_by_field_name("name")
            if name_node:
                return name_node.text.decode()
            for child in parent.children:
                if child.type == "identifier":
                    return child.text.decode()
        return "<anonymous>"
    return "<anonymous>"


collect_functions = collect_functions_wrapper(_collect_functions_recursive)
func_param_count = func_param_count_wrapper(param_count)
