"""Dr-Prompt SDK Data Models."""

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


@dataclass
class PromptVersion:
    """Represents a version of a prompt."""

    id: int
    version: int
    content: str
    created_at: datetime
    created_by: int
    prompt_id: Optional[int] = None

    @classmethod
    def from_dict(cls, data: dict) -> "PromptVersion":
        return cls(
            id=data["id"],
            version=data["version"],
            content=data["content"],
            created_at=datetime.fromisoformat(data["created_at"].replace("Z", "+00:00")),
            created_by=data["created_by"],
            prompt_id=data.get("prompt_id"),
        )


@dataclass
class Prompt:
    """Represents a prompt."""

    id: int
    uid: str
    name: str
    description: Optional[str]
    current_version: Optional[int]
    current_content: Optional[str]
    created_at: datetime
    updated_at: datetime
    versions: List[PromptVersion] = field(default_factory=list)
    _variables: List[str] = field(default_factory=list)

    @classmethod
    def from_dict(cls, data: dict) -> "Prompt":
        versions = []
        if "versions" in data:
            versions = [PromptVersion.from_dict(v) for v in data["versions"]]

        return cls(
            id=data["id"],
            uid=data["uid"],
            name=data["name"],
            description=data.get("description"),
            current_version=data.get("current_version"),
            current_content=data.get("current_content"),
            created_at=datetime.fromisoformat(data["created_at"].replace("Z", "+00:00")),
            updated_at=datetime.fromisoformat(data["updated_at"].replace("Z", "+00:00")),
            versions=versions,
        )

    def render(self, variables: Dict[str, str] = None) -> str:
        """
        Render the prompt content with template variables replaced.

        Args:
            variables: Dictionary of variable names to values.

        Returns:
            The rendered prompt content.
        """
        content = self.current_content or ""
        if variables:
            for key, value in variables.items():
                content = content.replace(f"{{{{{key}}}}}", str(value))
        return content

    def get_variables(self) -> List[str]:
        """
        Extract template variables from the prompt content.

        Returns:
            List of variable names found in the prompt.
        """
        import re

        if self.current_content:
            pattern = r"\{\{(\w+)\}\}"
            return list(set(re.findall(pattern, self.current_content)))
        return []


@dataclass
class Collection:
    """Represents a collection of prompts."""

    id: int
    name: str
    description: Optional[str]
    color: str
    prompt_count: int
    created_at: datetime
    updated_at: datetime
    prompts: List[Dict[str, Any]] = field(default_factory=list)

    @classmethod
    def from_dict(cls, data: dict) -> "Collection":
        return cls(
            id=data["id"],
            name=data["name"],
            description=data.get("description"),
            color=data.get("color", "#00ff88"),
            prompt_count=data.get("prompt_count", len(data.get("prompts", []))),
            created_at=datetime.fromisoformat(data["created_at"].replace("Z", "+00:00")),
            updated_at=datetime.fromisoformat(data["updated_at"].replace("Z", "+00:00")),
            prompts=data.get("prompts", []),
        )


@dataclass
class UsageStats:
    """Represents usage statistics."""

    total_calls: int
    total_input_tokens: int
    total_output_tokens: int
    calls_today: int
    calls_this_week: int
    calls_this_month: int

    @classmethod
    def from_dict(cls, data: dict) -> "UsageStats":
        return cls(
            total_calls=data["total_calls"],
            total_input_tokens=data["total_input_tokens"],
            total_output_tokens=data["total_output_tokens"],
            calls_today=data["calls_today"],
            calls_this_week=data["calls_this_week"],
            calls_this_month=data["calls_this_month"],
        )

    @property
    def total_tokens(self) -> int:
        """Total tokens (input + output)."""
        return self.total_input_tokens + self.total_output_tokens
