"""Entry point detection for tree-sitter.

Detects application entry points in JavaScript and TypeScript files:
- Express/Fastify/Koa app creation
- app.listen() calls
- Default exports in index files
- CommonJS require.main patterns
"""

from __future__ import annotations

from typing import TYPE_CHECKING

from unfamiliar.analysis.adapters._treesitter_utils import get_node_text, traverse
from unfamiliar.analysis.models import EntryPoint
from unfamiliar.constants import EntryType

if TYPE_CHECKING:
    from tree_sitter import Node


def extract_entry_points(root: Node, file_path: str) -> list[EntryPoint]:
    """Detect entry points in JS/TS files.

    Detection heuristics:
    - Express/Fastify/Koa app creation (EntryType.API_ROUTE)
    - app.listen() calls (EntryType.API_ROUTE)
    - Default export in index file (EntryType.MAIN)
    - if (require.main === module) pattern (EntryType.MAIN)

    Args:
        root: The root node of the parsed JS/TS file.
        file_path: Path of the file being analyzed.

    Returns:
        List of EntryPoint objects for detected entry points.
    """
    entry_points: list[EntryPoint] = []
    file_name = file_path.split("/")[-1] if "/" in file_path else file_path
    is_index = file_name in ("index.js", "index.ts", "index.jsx", "index.tsx")

    for node in traverse(root):
        # Check for app creation: const app = express(), const app = fastify()
        if node.type == "variable_declarator":
            name_node = node.child_by_field_name("name")
            value_node = node.child_by_field_name("value")

            if name_node and value_node and value_node.type == "call_expression":
                var_name = get_node_text(name_node)
                func = value_node.child_by_field_name("function")

                if func:
                    func_name = get_node_text(func)
                    if func_name in ("express", "fastify", "Fastify"):
                        entry_points.append(
                            EntryPoint(
                                file_path=file_path,
                                entry_type=EntryType.API_ROUTE,
                                description=f"Express/Fastify app creation: {var_name}",
                                line=node.start_point.row + 1,
                            )
                        )
                    elif func_name == "Koa":
                        entry_points.append(
                            EntryPoint(
                                file_path=file_path,
                                entry_type=EntryType.API_ROUTE,
                                description=f"Koa app creation: {var_name}",
                                line=node.start_point.row + 1,
                            )
                        )

        # Check for new Koa()
        if node.type == "new_expression":
            constructor = node.child_by_field_name("constructor")
            if constructor:
                ctor_name = get_node_text(constructor)
                if ctor_name == "Koa":
                    entry_points.append(
                        EntryPoint(
                            file_path=file_path,
                            entry_type=EntryType.API_ROUTE,
                            description="Koa app creation (new Koa())",
                            line=node.start_point.row + 1,
                        )
                    )

        # Check for app.listen() calls
        if node.type == "call_expression":
            func = node.child_by_field_name("function")
            if func and func.type == "member_expression":
                obj = func.child_by_field_name("object")
                prop = func.child_by_field_name("property")

                if obj and prop:
                    obj_name = get_node_text(obj)
                    prop_name = get_node_text(prop)

                    if prop_name == "listen" and obj_name in ("app", "server"):
                        entry_points.append(
                            EntryPoint(
                                file_path=file_path,
                                entry_type=EntryType.API_ROUTE,
                                description=f"{obj_name}.listen() call",
                                line=node.start_point.row + 1,
                            )
                        )

        # Check for default export in index file
        if node.type == "export_statement" and is_index:
            # Check if any child is the "default" keyword
            has_default = any(child.type == "default" for child in node.children)
            if has_default:
                entry_points.append(
                    EntryPoint(
                        file_path=file_path,
                        entry_type=EntryType.MAIN,
                        description="Default export in index file",
                        line=node.start_point.row + 1,
                    )
                )

        # Check for require.main === module pattern (CommonJS entry)
        if node.type == "if_statement":
            condition = node.child_by_field_name("condition")
            if condition:
                condition_text = get_node_text(condition)
                if "require.main" in condition_text and "module" in condition_text:
                    entry_points.append(
                        EntryPoint(
                            file_path=file_path,
                            entry_type=EntryType.MAIN,
                            description="if (require.main === module) pattern",
                            line=node.start_point.row + 1,
                        )
                    )

    return entry_points
