# models/kick_models.py
from datetime import datetime
from typing import List, Optional, Dict, Any

from pydantic import BaseModel, EmailStr, Field, field_validator, model_validator

from common.models.common import ChatMessage


class KickUser(BaseModel):
    """Base model for Kick user information."""

    email: Optional[EmailStr] = None
    user_id: int
    username: str  # Primary field from Kick webhooks
    name: Optional[str] = None  # Alias for username (for backward compatibility)
    channel_slug: str  # Channel identifier for URLs (required in webhooks)
    profile_picture: Optional[str] = None
    is_anonymous: Optional[bool] = None
    is_verified: Optional[bool] = None

    @field_validator("name", mode="before")
    @classmethod
    def set_name_from_username(cls, v: Optional[str], info) -> Optional[str]:
        """Set name to username if not provided for backward compatibility."""
        if v is None and "username" in info.data:
            return info.data["username"]
        return v


class KickApiUser(BaseModel):
    """Model for Kick /users API responses (distinct from webhook payloads)."""

    email: Optional[EmailStr] = None
    user_id: int
    name: Optional[str] = None
    username: Optional[str] = None
    channel_slug: Optional[str] = None
    profile_picture: Optional[str] = None

    @model_validator(mode="after")
    def normalize_display_identity(self) -> "KickApiUser":
        """Keep name/username aligned so consumers can use either field."""
        if not self.username and self.name:
            self.username = self.name
        if not self.name and self.username:
            self.name = self.username
        return self


class KickBadge(BaseModel):
    """Model for Kick user badges."""

    text: str
    type: str
    count: Optional[int] = None


class KickIdentity(BaseModel):
    """Model for Kick user identity information."""

    username_color: Optional[str] = None
    badges: Optional[List[KickBadge]] = None


class KickEmote(BaseModel):
    """Model for Kick emotes in chat messages."""

    emote_id: str
    positions: List[Dict[str, int]]  # Contains 's' (start) and 'e' (end) positions


class KickChatMessage(ChatMessage):
    """Model for Kick chat message webhook payload."""

    message_id: str
    broadcaster: KickUser
    sender: KickUser
    content: str
    emotes: Optional[List[KickEmote]] = None
    created_at: datetime

    def get_content(self) -> str:
        return self.content

    def get_timestamp(self) -> float:
        return self.created_at.timestamp()

    def get_broadcaster_user_id(self) -> str:
        # Return as string to align with ChatMessage abstract contract
        return str(self.broadcaster.user_id)


class KickChannelFollow(BaseModel):
    """Model for Kick channel follow webhook payload."""

    broadcaster: KickUser
    follower: KickUser


class KickSubscription(BaseModel):
    """Base model for Kick subscription events."""

    broadcaster: KickUser
    subscriber: KickUser
    duration: int
    created_at: datetime
    expires_at: datetime


class KickSubscriptionRenewal(KickSubscription):
    """Model for Kick subscription renewal webhook payload."""

    pass


class KickSubscriptionNew(KickSubscription):
    """Model for Kick new subscription webhook payload."""

    pass


class KickSubscriptionGift(BaseModel):
    """Model for Kick subscription gift webhook payload."""

    broadcaster: KickUser
    gifter: KickUser
    giftees: List[KickUser]
    created_at: datetime
    expires_at: datetime


class KickLivestreamStatus(BaseModel):
    """Model for Kick livestream status webhook payload."""

    broadcaster: Dict[str, Any]
    is_live: bool
    title: str
    started_at: Optional[datetime] = None
    ended_at: Optional[datetime] = None


# API Response Models
class KickTokenIntrospectResponse(BaseModel):
    """Model for Kick token introspect API response."""

    data: Dict[str, Any]
    message: str


class KickUserResponse(BaseModel):
    """Model for Kick user API response."""

    data: List[KickApiUser]
    message: str


class KickChannelResponse(BaseModel):
    """Model for Kick channel API response."""

    data: List[Dict[str, Any]]
    message: str


class KickLivestreamResponse(BaseModel):
    """Model for Kick livestream API response."""

    data: List[Dict[str, Any]]
    message: str


class KickEventSubscription(BaseModel):
    """Model for Kick event subscription."""

    app_id: str
    broadcaster_user_id: int
    created_at: str
    event: str
    id: str
    method: str
    updated_at: str
    version: int


class KickEventSubscriptionsResponse(BaseModel):
    """Model for Kick event subscriptions API response."""

    data: List[KickEventSubscription]
    message: str


class KickEventSubscriptionRequest(BaseModel):
    """Model for Kick event subscription request."""

    broadcaster_user_id: int
    events: List[Dict[str, Any]]
    method: str = "webhook"
    webhook_url: Optional[str] = None  # URL where Kick will send webhooks


class KickEventSubscriptionResult(BaseModel):
    """Model for individual subscription result in response."""

    error: Optional[str] = None
    name: str
    subscription_id: str
    version: int


class KickEventSubscriptionResponse(BaseModel):
    """Model for Kick event subscription API response."""

    data: List[KickEventSubscriptionResult]
    message: str


class KickAuthorizeParams(BaseModel):
    """Model for Kick authorization parameters."""

    client_id: str
    redirect_uri: str
    response_type: str = "code"
    scope: str
    state: Optional[str] = None
    code_challenge: str
    code_challenge_method: str = "S256"


class KickChatMessageRequest(BaseModel):
    """Model for Kick chat message request."""

    broadcaster_user_id: int
    content: str = Field(max_length=500)
    reply_to_message_id: Optional[str] = None
    type: str = "user"


class KickChatMessageResponseData(BaseModel):
    """Model for Kick chat message response data."""

    is_sent: bool
    message_id: str


class KickChatMessageResponse(BaseModel):
    """Model for Kick chat message response."""

    data: KickChatMessageResponseData
    message: str
    error: Optional[str] = None


__all__ = [
    "KickUser",
    "KickApiUser",
    "KickBadge",
    "KickIdentity",
    "KickEmote",
    "KickChatMessage",
    "KickChannelFollow",
    "KickSubscription",
    "KickSubscriptionRenewal",
    "KickSubscriptionNew",
    "KickSubscriptionGift",
    "KickLivestreamStatus",
    "KickTokenIntrospectResponse",
    "KickUserResponse",
    "KickChannelResponse",
    "KickLivestreamResponse",
    "KickEventSubscription",
    "KickEventSubscriptionsResponse",
    "KickEventSubscriptionRequest",
    "KickEventSubscriptionResult",
    "KickEventSubscriptionResponse",
    "KickAuthorizeParams",
    "KickChatMessageRequest",
    "KickChatMessageResponseData",
    "KickChatMessageResponse",
]
