"""Pydantic models for CRDT document parsing results.

This module defines data models for parsed CRDT documents containing
ProseMirror schema structures for various social media platforms.
"""

from __future__ import annotations

from datetime import UTC, datetime
from enum import StrEnum
from typing import Any

from pydantic import BaseModel, ConfigDict, Field


class Platform(StrEnum):
    """Supported social media platforms."""

    TWITTER = "twitter"
    LINKEDIN = "linkedin"
    INSTAGRAM = "instagram"
    TIKTOK = "tiktok"


class ContentType(StrEnum):
    """Content types for posts."""

    POST = "POST"
    FEED = "FEED"
    REEL = "REEL"
    STORY = "STORY"
    CAROUSEL = "CAROUSEL"


class PostVisibility(StrEnum):
    """LinkedIn post visibility settings."""

    PUBLIC = "PUBLIC"
    CONNECTIONS = "CONNECTIONS"
    LOGGED_IN = "LOGGED_IN"


# ==================== Platform Content Models ====================


class AutoNumberConfig(BaseModel):
    """Configuration for thread auto-numbering.

    Attributes:
        enabled: Whether auto-numbering is active
        position: Where to insert number in tweet ("start" or "end")
        format_style: Format template (e.g., "#1")
        skip_first: Cards to skip from start
        skip_last: Cards to skip from end
    """

    enabled: bool = False
    position: str = "start"
    format_style: str = "#1"
    skip_first: int = 1
    skip_last: int = 1

    model_config = ConfigDict(frozen=True)


class TwitterCardContent(BaseModel):
    """Represents content of a single Twitter card (tweet).

    Attributes:
        id: Unique identifier for the card within the document
        text: Text content of the tweet
        media: List of media URLs (space-separated URLs split into list)
        is_quoted: Whether this card quotes another tweet
        quoted_card_id: ID of the quoted card within the document
        quoted_tweet_id: Extracted tweet ID from og URL when quoteOg is true
        auto_number: Pre-computed numbering text (e.g., "1/", "#1")
    """

    id: str | None = None
    text: str = ""
    media: list[str] = Field(default_factory=list)
    is_quoted: bool = False
    quoted_card_id: str | None = None
    quoted_tweet_id: str | None = None
    auto_number: str | None = None

    model_config = ConfigDict(frozen=True)


class LinkedInPostContent(BaseModel):
    """Represents content of a LinkedIn post.

    Attributes:
        id: Post node ID from schema
        text: Text content of the post
        media: List of media URLs
        pdf: PDF data string
        visibility: Post visibility setting
    """

    id: str | None = None
    text: str = ""
    media: list[str] = Field(default_factory=list)
    pdf: str | None = None
    visibility: PostVisibility = PostVisibility.PUBLIC

    model_config = ConfigDict(frozen=True)


class LinkedInCommentContent(BaseModel):
    """Represents content of a LinkedIn first comment.

    Attributes:
        id: Comment node ID from schema
        text: Text content of the comment
    """

    id: str | None = None
    text: str = ""

    model_config = ConfigDict(frozen=True)


class InstagramPostContent(BaseModel):
    """Represents content of an Instagram post.

    Attributes:
        id: Post node ID from schema
        caption: Caption text of the post
        media: List of media URLs
        content_type: Type of Instagram content
        location: Location ID string
        music: Music string
    """

    id: str | None = None
    caption: str = ""
    media: list[str] = Field(default_factory=list)
    content_type: ContentType = ContentType.POST
    location: str | None = None
    music: str | None = None

    model_config = ConfigDict(frozen=True)


class TikTokPostContent(BaseModel):
    """Represents content of a TikTok post.

    Attributes:
        id: Post node ID from schema
        title: Title/description of the video
        media: List of media URLs
        location: Location string
        music: Music string
    """

    id: str | None = None
    title: str = ""
    media: list[str] = Field(default_factory=list)
    location: str | None = None
    music: str | None = None

    model_config = ConfigDict(frozen=True)


# ==================== Document Result Models ====================


class ParsedTwitterDocument(BaseModel):
    """Result of parsing a Twitter CRDT document.

    Attributes:
        cards: List of parsed Twitter cards (tweets in thread)
        auto_number_config: Thread-level auto-numbering config from twitterthread node
        raw_attributes: Original document attributes
        parsed_at: Timestamp when document was parsed
    """

    cards: list[TwitterCardContent] = Field(default_factory=list)
    auto_number_config: AutoNumberConfig | None = None
    raw_attributes: dict[str, Any] = Field(default_factory=dict)
    parsed_at: datetime = Field(default_factory=lambda: datetime.now(UTC))

    model_config = ConfigDict(frozen=True)


class ParsedLinkedInDocument(BaseModel):
    """Result of parsing a LinkedIn CRDT document.

    Attributes:
        post: Parsed LinkedIn post content
        comment: Optional first comment content
        raw_attributes: Original document attributes
        parsed_at: Timestamp when document was parsed
    """

    post: LinkedInPostContent
    comment: LinkedInCommentContent | None = None
    raw_attributes: dict[str, Any] = Field(default_factory=dict)
    parsed_at: datetime = Field(default_factory=lambda: datetime.now(UTC))

    model_config = ConfigDict(frozen=True)


class ParsedInstagramDocument(BaseModel):
    """Result of parsing an Instagram CRDT document.

    Attributes:
        post: Parsed Instagram post content
        raw_attributes: Original document attributes
        parsed_at: Timestamp when document was parsed
    """

    post: InstagramPostContent
    raw_attributes: dict[str, Any] = Field(default_factory=dict)
    parsed_at: datetime = Field(default_factory=lambda: datetime.now(UTC))

    model_config = ConfigDict(frozen=True)


class ParsedTikTokDocument(BaseModel):
    """Result of parsing a TikTok CRDT document.

    Attributes:
        post: Parsed TikTok post content
        raw_attributes: Original document attributes
        parsed_at: Timestamp when document was parsed
    """

    post: TikTokPostContent
    raw_attributes: dict[str, Any] = Field(default_factory=dict)
    parsed_at: datetime = Field(default_factory=lambda: datetime.now(UTC))

    model_config = ConfigDict(frozen=True)


# Type alias for any parsed document result
type ParsedDocument = (
    ParsedTwitterDocument
    | ParsedLinkedInDocument
    | ParsedInstagramDocument
    | ParsedTikTokDocument
)
