"""
Data classes for extracted code elements.
"""

from dataclasses import dataclass, field
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from tree_sitter import Node


@dataclass
class ExtractedFunction:
    """Extracted function or method information."""

    name: str
    qualified_name: str
    start_line: int
    end_line: int
    signature: str
    docstring: str | None = None
    decorators: list[str] = field(default_factory=list)
    is_async: bool = False
    is_method: bool = False
    is_public: bool = True
    class_name: str | None = None
    parameters: list[str] = field(default_factory=list)
    return_type: str | None = None
    source_code: str = ""
    local_type_map: dict[str, str] = field(default_factory=dict)
    node: "Node | None" = field(default=None, repr=False)

    def to_dict(self) -> dict:
        """Serialize all fields except node."""
        return {
            "name": self.name,
            "qualified_name": self.qualified_name,
            "start_line": self.start_line,
            "end_line": self.end_line,
            "signature": self.signature,
            "docstring": self.docstring,
            "decorators": self.decorators,
            "is_async": self.is_async,
            "is_method": self.is_method,
            "is_public": self.is_public,
            "class_name": self.class_name,
            "parameters": self.parameters,
            "return_type": self.return_type,
            "source_code": self.source_code,
            "local_type_map": self.local_type_map,
        }


@dataclass
class ExtractedClass:
    """Extracted class information."""

    name: str
    qualified_name: str
    start_line: int
    end_line: int
    docstring: str | None = None
    decorators: list[str] = field(default_factory=list)
    bases: list[str] = field(default_factory=list)
    methods: list[ExtractedFunction] = field(default_factory=list)
    is_public: bool = True
    source_code: str = ""
    node: "Node | None" = field(default=None, repr=False)

    def to_dict(self) -> dict:
        """Serialize all fields except node, with methods serialized via to_dict()."""
        return {
            "name": self.name,
            "qualified_name": self.qualified_name,
            "start_line": self.start_line,
            "end_line": self.end_line,
            "docstring": self.docstring,
            "decorators": self.decorators,
            "bases": self.bases,
            "methods": [m.to_dict() for m in self.methods],
            "is_public": self.is_public,
            "source_code": self.source_code,
        }


@dataclass
class ExtractedCall:
    """Extracted function call information."""

    name: str
    line: int
    caller_qualified_name: str
    receiver: str | None = None
    arguments: list[str] = field(default_factory=list)
    call_type: str = "direct"

    def to_dict(self) -> dict:
        """Serialize all fields."""
        return {
            "name": self.name,
            "line": self.line,
            "caller_qualified_name": self.caller_qualified_name,
            "receiver": self.receiver,
            "arguments": self.arguments,
            "call_type": self.call_type,
        }


@dataclass
class ExtractedImport:
    """Extracted import statement."""

    module: str
    name: str | None = None
    alias: str | None = None
    is_wildcard: bool = False
    line: int = 0

    def to_dict(self) -> dict:
        """Serialize all fields."""
        return {
            "module": self.module,
            "name": self.name,
            "alias": self.alias,
            "is_wildcard": self.is_wildcard,
            "line": self.line,
        }


@dataclass
class ParseResult:
    """Container for all extracted elements from a file."""

    file_path: str
    language: str
    functions: list[ExtractedFunction] = field(default_factory=list)
    classes: list[ExtractedClass] = field(default_factory=list)
    imports: list[ExtractedImport] = field(default_factory=list)
    calls: list[ExtractedCall] = field(default_factory=list)
    module_level_calls: list[ExtractedCall] = field(default_factory=list)
    error: str | None = None

    def to_dict(self) -> dict:
        """Serialize all fields, with nested lists serialized via to_dict()."""
        return {
            "file_path": self.file_path,
            "language": self.language,
            "functions": [f.to_dict() for f in self.functions],
            "classes": [c.to_dict() for c in self.classes],
            "imports": [i.to_dict() for i in self.imports],
            "calls": [c.to_dict() for c in self.calls],
            "module_level_calls": [c.to_dict() for c in self.module_level_calls],
            "error": self.error,
        }
