from datetime import datetime
from typing import Optional

from pydantic import BaseModel, field_validator

from common.models.common import Platform
from common.platform.twitch.model import User


class TldrMessage(BaseModel):
    """
    Pydantic model for a message sent to the TLDR service.
    """

    # Base class for all TLDR messages


class UserSignupMessage(TldrMessage):
    """
    Pydantic model for a message sent when a user signs up.
    """

    user: User


class StreamOnlineMessage(TldrMessage):
    """
    Pydantic model for a message sent when a stream goes online.
    """

    stream_id: str
    channel_name: str
    game_name: str
    user_id: int
    started_at: datetime
    platform: str

    @field_validator("stream_id", mode="before")
    @classmethod
    def _coerce_stream_id(cls, value: object) -> object:
        if value is None or isinstance(value, str):
            return value
        return str(value)


class StreamOfflineMessage(TldrMessage):
    """
    Pydantic model for a message sent when a stream goes offline.
    """

    channel_name: str
    user_id: int
    ended_at: datetime
    stream_id: Optional[str] = None  # Optional for RTMP streams

    @field_validator("stream_id", mode="before")
    @classmethod
    def _coerce_stream_id(cls, value: object) -> object:
        if value is None or isinstance(value, str):
            return value
        return str(value)


class VoiceClipMessage(TldrMessage):
    """
    Message indicating the wake word was detected.
    """

    stream_id: str
    timestamp: datetime
    wake_word: str = "TL;DR clip"
    clip_url: str
    broadcaster_user_id: str
    user_id: int
    clip_id: Optional[str] = None  # Optional clip ID for tracking
    platform: Platform = Platform.TWITCH  # Platform where clip was created


class AIClipMessage(TldrMessage):
    """
    Message indicating an AI-generated clip was created.
    """

    stream_id: str
    timestamp: datetime
    clip_url: str
    broadcaster_user_id: str
    user_id: int
    clip_id: Optional[str] = None  # Optional clip ID for tracking
    platform: Platform = Platform.TWITCH  # Platform where clip was created


class UserEventSub(TldrMessage):
    """
    Message indicating that a user should be subscribed to the platform eventsub.
    """

    user_id: int
    platform_id: str
    platform: Platform


class StreamProcessingRequest(TldrMessage):
    """
    Request to start processing a stream for highlight detection.
    """

    stream_id: str
    channel_name: str
    user_id: int
    platform: Platform
    game_name: str
    started_at: datetime

    @field_validator("stream_id", mode="before")
    @classmethod
    def _coerce_stream_id(cls, value: object) -> object:
        if value is None or isinstance(value, str):
            return value
        return str(value)


class StreamProcessingStatus(TldrMessage):
    """
    Status update from stream processing agent.
    """

    stream_id: str
    agent_id: str
    status: str  # "active", "stopping", "stopped", "error"
    segments_processed: int
    highlights_created: int
    error_message: Optional[str] = None


class ClipCreatedMessage(TldrMessage):
    """
    Notification when a clip is created and uploaded.
    """

    clip_id: str
    stream_id: str
    channel_name: str
    platform: Platform
    clip_type: str  # "wake_word" or "ai_highlight"
    s3_url: str
    s3_thumbnail_url: Optional[str] = None
    start_timestamp: float
    end_timestamp: float
    duration: float
    title: str
    description: str
    game_name: Optional[str] = None
    created_at: datetime


class ManualClipRequestMessage(TldrMessage):
    """Request to create a manual clip (Stream Deck trigger)."""

    request_id: str
    user_id: int
    stream_id: str
    platform: str
    clip_duration_seconds: int = 60
    timestamp: datetime
