"""Context — modelo unificado de contexto indexable y buscable."""

from __future__ import annotations

from dataclasses import dataclass, field
from datetime import datetime
from typing import Any


@dataclass
class Context:
    """Modelo unificado de contexto que representa cualquier recurso indexable.

    Representa documentos, memorias o skills almacenados en una base de datos
    vectorial. Combina metadata, jerarquia de directorios (via URI), conteo de
    accesos para hotness scoring, y relaciones entre contextos.

    Attributes:
        id:           UUID unico del contexto.
        uri:          Identificador unico del recurso, estilo filesystem.
                      Ejemplo: ``viking://resources/docs/readme.md``
        parent_uri:   URI del nodo padre (directorio que lo contiene).
                      None si es la raiz.
        is_leaf:      True si es un nodo hoja (archivo), False si es directorio.
        abstract:     Resumen corto del contenido (L0, ~256 chars).
        context_type: Categoria semantica del contexto.
                      Valores tipicos: "memory", "resource", "skill".
        category:     Subcategoria libre para clasificacion adicional.
        level:        Nivel de detalle (ContextLevel: 0=ABSTRACT, 1=OVERVIEW, 2=DETAIL).
                      None si no se ha asignado nivel.
        created_at:   Timestamp de creacion (UTC). None si desconocido.
        updated_at:   Timestamp de ultima actualizacion (UTC). None si desconocido.
        active_count: Numero de veces que el contexto fue recuperado.
                      Usado por hotness_score() para priorizar resultados frecuentes.
        related_uri:  Lista de URIs de contextos relacionados. Permite grafos de relaciones.
        meta:         Datos arbitrarios adicionales (parametros, etiquetas, etc.).
    """

    id: str
    uri: str
    parent_uri: str | None = None
    is_leaf: bool = False
    abstract: str = ""
    context_type: str = "resource"
    category: str = ""
    level: int | None = None
    created_at: datetime | None = None
    updated_at: datetime | None = None
    active_count: int = 0
    related_uri: list[str] = field(default_factory=list)
    meta: dict[str, Any] = field(default_factory=dict)

    def to_dict(self) -> dict:
        """Serializa el contexto a dict con timestamps en formato ISO 8601.

        Returns:
            dict con todos los campos listos para JSON o almacenamiento en BD.
        """
        return {
            "id": self.id,
            "uri": self.uri,
            "parent_uri": self.parent_uri,
            "is_leaf": self.is_leaf,
            "abstract": self.abstract,
            "context_type": self.context_type,
            "category": self.category,
            "level": self.level,
            "created_at": self.created_at.isoformat() if self.created_at else None,
            "updated_at": self.updated_at.isoformat() if self.updated_at else None,
            "active_count": self.active_count,
            "related_uri": self.related_uri,
            "meta": self.meta,
        }

    @classmethod
    def from_dict(cls, data: dict) -> "Context":
        """Deserializa un Context desde un dict (inverso de to_dict).

        Args:
            data: dict con los campos del contexto. Los timestamps pueden ser
                  strings ISO 8601 o None.

        Returns:
            Instancia de Context con los valores del dict.
        """
        created_at = data.get("created_at")
        updated_at = data.get("updated_at")
        return cls(
            id=data["id"],
            uri=data["uri"],
            parent_uri=data.get("parent_uri"),
            is_leaf=data.get("is_leaf", False),
            abstract=data.get("abstract", ""),
            context_type=data.get("context_type", "resource"),
            category=data.get("category", ""),
            level=data.get("level"),
            created_at=datetime.fromisoformat(created_at) if isinstance(created_at, str) else created_at,
            updated_at=datetime.fromisoformat(updated_at) if isinstance(updated_at, str) else updated_at,
            active_count=data.get("active_count", 0),
            related_uri=data.get("related_uri", []),
            meta=data.get("meta", {}),
        )
