from datetime import datetime
from typing import Any, Dict, Literal, Optional
from enum import Enum
from uuid import UUID

from pydantic import BaseModel, Field, ConfigDict


class EmojiType(str, Enum):
    """Supported emoji reaction types for clips."""

    HEART = "heart"
    SMILE = "smile"
    LAUGH = "laugh"
    SIGN = "sign"
    SURPRISED = "surprised"


class ClipAnalyticsBase(BaseModel):
    clip_id: int
    views: int = 0
    heart_reactions: int = 0
    smile_reactions: int = 0
    laugh_reactions: int = 0
    sign_reactions: int = 0
    surprised_reactions: int = 0


class ClipAnalyticsCreate(ClipAnalyticsBase):
    pass


class ClipAnalyticsUpdate(BaseModel):
    views: Optional[int] = None
    heart_reactions: Optional[int] = None
    smile_reactions: Optional[int] = None
    laugh_reactions: Optional[int] = None
    sign_reactions: Optional[int] = None
    surprised_reactions: Optional[int] = None


class ClipAnalytics(ClipAnalyticsBase):
    id: int
    created_at: datetime
    updated_at: datetime
    deleted_at: Optional[datetime] = None


class ClipBase(BaseModel):
    url: Optional[str] = None
    kind: str
    stream_id: int
    thumbnail_url: Optional[str] = None
    watermark_url: Optional[str] = None
    caption: Optional[str] = None
    favorited: bool = False
    views: int = 0
    start_time: int
    owner_username: Optional[str] = None
    user_id: int
    source_type: Literal["stream", "upload"] = "stream"
    upload_session_id: Optional[UUID] = None
    # Prompt metadata fields for measurement infrastructure
    prompt_version: Optional[str] = None
    dimension_scores: Optional[Dict[str, Any]] = None
    combined_score: Optional[float] = None
    game_config_name: Optional[str] = None


class ClipCreate(ClipBase):
    pass


class ClipUpdate(BaseModel):
    url: Optional[str] = None
    kind: Optional[str] = None
    thumbnail_url: Optional[str] = None
    watermark_url: Optional[str] = None
    caption: Optional[str] = None
    views: Optional[int] = None
    favorited: Optional[bool] = None
    start_time: Optional[int] = None
    owner_username: Optional[str] = None
    user_id: Optional[int] = None


class Clip(ClipBase):
    id: int
    created_at: datetime
    updated_at: datetime
    deleted_at: Optional[datetime] = None
    platform: Optional[str] = None
    analytics: Optional[ClipAnalytics] = None
    # Prompt metadata fields inherited from ClipBase
    # prompt_version, dimension_scores, combined_score, game_config_name


# Models for Edited Clips
class EditedClipBase(BaseModel):
    """Base fields for an edited clip variant."""

    original_clip_id: int
    url: str = Field(description="S3 key or URL to the edited clip")
    name: Optional[str] = Field(None, description="Optional user-provided name")
    metadata: Optional[Dict[str, Any]] = Field(
        None, description="Optional metadata for the edited clip"
    )
    thumbnail_url: Optional[str] = Field(
        None, description="Optional thumbnail URL for the edited clip"
    )


class EditedClipCreate(EditedClipBase):
    """Data required to create a new edited clip record."""

    pass


class EditedClipUpdate(BaseModel):
    """Data required to update an edited clip record."""

    url: Optional[str] = Field(None, description="S3 key or URL to the edited clip")
    name: Optional[str] = Field(None, description="Optional user-provided name")
    metadata: Optional[Dict[str, Any]] = Field(
        None, description="Optional metadata for the edited clip"
    )
    thumbnail_url: Optional[str] = Field(
        None, description="Optional thumbnail URL for the edited clip"
    )


class EditedClip(EditedClipBase):
    """Edited clip record returned from the database."""

    id: int
    created_at: datetime
    updated_at: datetime
    deleted_at: Optional[datetime] = None

    model_config = ConfigDict(from_attributes=True)


class ClipLimitsStatus(BaseModel):
    clips_last_day: int
    clips_last_month: int
    max_clips_per_day: int
    max_clips_per_month: int
