"""Data models for zymemory SDK."""

from typing import List, Dict, Any, Optional
from dataclasses import dataclass


@dataclass
class Memory:
    """Represents a memory in the system.

    Attributes:
        id: Unique memory identifier
        content: The memory content/text
        keywords: List of extracted keywords
        conversations: List of conversation turns
        created_at: ISO timestamp of creation
        link_count: Number of connections to other memories
    """
    id: int
    content: str
    keywords: List[str]
    conversations: List[tuple[str, str]]
    created_at: Optional[str] = None
    link_count: Optional[int] = None
    metadata: Optional[Dict[str, Any]] = None

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "Memory":
        """Create Memory from API response dictionary."""
        metadata = data.get("metadata", {})
        return cls(
            id=data["id"],
            content=data["content"],
            keywords=metadata.get("keywords", []),
            conversations=metadata.get("conversations", []),
            created_at=data.get("created_at"),
            link_count=metadata.get("link_count"),
            metadata=metadata
        )


@dataclass
class SearchResult:
    """Result from memory search.

    Attributes:
        memories: List of matching memories
        unassigned: List of unassigned conversation turns
    """
    memories: List[Memory]
    unassigned: List[Dict[str, Any]]

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "SearchResult":
        """Create SearchResult from API response."""
        memories = [Memory.from_dict(m) for m in data.get("memories", [])]
        return cls(
            memories=memories,
            unassigned=data.get("unassigned", [])
        )


@dataclass
class MemoryList:
    """Paginated list of memories.

    Attributes:
        memories: List of memories on current page
        total: Total number of memories
        page: Current page number
        page_size: Number of items per page
    """
    memories: List[Memory]
    total: int
    page: int
    page_size: int

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "MemoryList":
        """Create MemoryList from API response."""
        memories = [Memory.from_dict(m) for m in data.get("memories", [])]
        return cls(
            memories=memories,
            total=data["total"],
            page=data["page"],
            page_size=data["page_size"]
        )


@dataclass
class MemoryLink:
    """Link between two memories.

    Attributes:
        source_id: ID of source memory
        destination_id: ID of destination memory
        relationship: Type of relationship (optional)
    """
    source_id: int
    destination_id: int
    relationship: Optional[str] = None


@dataclass
class Representation:
    """Memory representation (versioned user instruction).

    Attributes:
        rung_id: Memory ID this representation belongs to
        version_num: Version number
        repr: Representation data dictionary
        created_at: Unix timestamp of creation
    """
    rung_id: int
    version_num: int
    repr: Dict[str, Any]
    created_at: Optional[int] = None

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "Representation":
        """Create Representation from API response."""
        return cls(
            rung_id=data["rung_id"],
            version_num=data["version_num"],
            repr=data["repr"],
            created_at=data.get("created_at")
        )


@dataclass
class RepresentationVersion:
    """Summary of a representation version.

    Attributes:
        version_num: Version number
        created_at: Unix timestamp of creation
    """
    version_num: int
    created_at: int


@dataclass
class RepresentationVersions:
    """List of all representation versions.

    Attributes:
        rung_id: Memory ID
        head: Current HEAD version number
        versions: List of version summaries
    """
    rung_id: int
    head: Optional[int]
    versions: List[RepresentationVersion]

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "RepresentationVersions":
        """Create RepresentationVersions from API response."""
        versions = [
            RepresentationVersion(
                version_num=v["version_num"],
                created_at=v["created_at"]
            ) for v in data.get("versions", [])
        ]
        return cls(
            rung_id=data["rung_id"],
            head=data.get("head"),
            versions=versions
        )


@dataclass
class Tenant:
    """User with access to a memory.

    Attributes:
        user_id: User ID
        role: Access role (0=read, 1=write, 2=owner)
    """
    user_id: int
    role: int


@dataclass
class MemoryAccess:
    """Access control list for a memory.

    Attributes:
        rung_id: Memory ID
        tenants: List of users with access
    """
    rung_id: int
    tenants: List[Tenant]

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "MemoryAccess":
        """Create MemoryAccess from API response."""
        tenants = [
            Tenant(user_id=t["user_id"], role=t["role"])
            for t in data.get("tenants", [])
        ]
        return cls(
            rung_id=data["rung_id"],
            tenants=tenants
        )


@dataclass
class User:
    """Registered user.

    Attributes:
        id: User identifier (optional, only returned in some endpoints)
        external_id: External identifier (optional)
        name: User name (optional)
        token: User API token
        created_at: Creation timestamp (optional)
    """
    token: str
    id: Optional[int] = None
    external_id: Optional[str] = None
    name: Optional[str] = None
    created_at: Optional[str] = None

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "User":
        """Create User from API response."""
        return cls(
            token=data["token"],
            id=data.get("id"),
            external_id=data.get("external_id"),
            name=data.get("name"),
            created_at=data.get("created_at")
        )
