"""ResourceNode — nodo en un arbol jerarquico de documento."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any

from node_type import NodeType


@dataclass
class ResourceNode:
    """Nodo en un arbol jerarquico de documento.

    Preserva la estructura natural del documento (secciones, subsecciones)
    sin perder contenido. Cada nodo puede tener hijos (subsecciones) y
    metadata arbitraria.

    Attributes:
        type:     Tipo del nodo (ROOT o SECTION).
        title:    Titulo de la seccion, None para el nodo raiz sin titulo.
        level:    Nivel de profundidad (0=root, 1=top section, 2=subsection, etc.).
        content:  Contenido markdown de este nodo (sin incluir el de hijos).
        children: Lista de nodos hijos (subsecciones).
        meta:     Metadata arbitraria del nodo.
    """

    type: NodeType
    title: str | None = None
    level: int = 0
    content: str = ""
    children: list[ResourceNode] = field(default_factory=list)
    meta: dict[str, Any] = field(default_factory=dict)

    def add_child(self, child: ResourceNode) -> None:
        """Agrega un nodo hijo a la lista de children.

        Args:
            child: Nodo hijo a agregar.
        """
        self.children.append(child)

    def get_text(self, include_children: bool = True) -> str:
        """Retorna el contenido concatenado del nodo y opcionalmente sus hijos.

        Args:
            include_children: Si True, incluye el contenido de todos los
                              descendientes de forma recursiva.

        Returns:
            String con el contenido completo.
        """
        parts = [self.content] if self.content else []
        if include_children:
            for child in self.children:
                child_text = child.get_text(include_children=True)
                if child_text:
                    parts.append(child_text)
        return "\n\n".join(parts)

    def get_abstract(self, max_length: int = 256) -> str:
        """Retorna un resumen corto: el titulo o los primeros N caracteres del contenido.

        Args:
            max_length: Longitud maxima del resumen en caracteres.

        Returns:
            String con el titulo o inicio del contenido, truncado si es necesario.
        """
        if self.title:
            return self.title[:max_length]
        text = self.content.strip()
        if len(text) <= max_length:
            return text
        return text[:max_length].rstrip() + "..."

    def get_overview(self, max_length: int = 4000) -> str:
        """Retorna un overview con el contenido del nodo y lista de secciones hijas.

        Args:
            max_length: Longitud maxima del overview en caracteres.

        Returns:
            String con el contenido del nodo seguido de los titulos de sus hijos.
        """
        parts = []
        if self.title:
            parts.append(f"# {self.title}")
        if self.content:
            parts.append(self.content)
        if self.children:
            child_titles = [
                f"- {child.title}" if child.title else f"- (section level {child.level})"
                for child in self.children
            ]
            parts.append("## Sections\n" + "\n".join(child_titles))
        overview = "\n\n".join(parts)
        if len(overview) <= max_length:
            return overview
        return overview[:max_length].rstrip() + "..."

    def to_dict(self) -> dict:
        """Serializa el nodo y sus descendientes a un diccionario.

        Returns:
            dict con todos los campos del nodo, con children serializado
            recursivamente.
        """
        return {
            "type": self.type.value,
            "title": self.title,
            "level": self.level,
            "content": self.content,
            "children": [child.to_dict() for child in self.children],
            "meta": self.meta,
        }

    @classmethod
    def from_dict(cls, data: dict) -> ResourceNode:
        """Deserializa un dict (producido por to_dict) a un ResourceNode.

        Args:
            data: Diccionario con los campos del nodo.

        Returns:
            ResourceNode reconstruido con todos sus descendientes.
        """
        return cls(
            type=NodeType(data["type"]),
            title=data.get("title"),
            level=data.get("level", 0),
            content=data.get("content", ""),
            children=[cls.from_dict(c) for c in data.get("children", [])],
            meta=data.get("meta", {}),
        )
