# chuk-motion/src/chuk_motion/tokens/captions.py
"""
Caption style system for platform-specific caption designs.

Caption styles enable:
- Platform-specific caption formatting (MrBeast, Kurzgesagt, LinkedIn, etc.)
- Transition animations
- Highlight styles
- Background styles
- Word-by-word vs. full-line display
- Scale and positioning presets

Critical for auto-generated captions that match platform best practices.
"""

from typing import Literal

from pydantic import BaseModel, Field

# ============================================================================
# PYDANTIC MODELS
# ============================================================================


class TypographyConfig(BaseModel):
    """Typography configuration for captions."""

    font_family: list[str] = Field(..., description="Font family list with fallbacks")
    font_weight: int = Field(..., description="Font weight (100-900)")
    font_size: int = Field(..., description="Font size in px")
    text_transform: Literal["none", "uppercase", "lowercase", "capitalize"] = Field(
        ..., description="Text transformation"
    )
    letter_spacing: str = Field(..., description="Letter spacing (e.g., '0.05em')")
    line_height: float = Field(..., description="Line height multiplier")


class ColorsConfig(BaseModel):
    """Colors configuration for captions."""

    text: str = Field(..., description="Text color")
    stroke: str | None = Field(None, description="Text stroke color")
    stroke_width: int = Field(0, description="Stroke width in px")
    shadow: str = Field(..., description="Text shadow CSS")


class BackgroundConfig(BaseModel):
    """Background configuration for captions."""

    enabled: bool = Field(..., description="Whether background is enabled")
    style: Literal["pill", "box", "none", "gradient"] = Field(..., description="Background style")
    color: str = Field(..., description="Background color or gradient")
    padding: str = Field(..., description="Padding CSS")
    border_radius: str = Field(..., description="Border radius CSS")
    blur: int = Field(0, description="Backdrop blur in px")
    border: str | None = Field(default=None, description="Border CSS")


class PositionConfig(BaseModel):
    """Position configuration for captions."""

    vertical: Literal["top", "center", "bottom", "lower_third"] = Field(
        ..., description="Vertical position"
    )
    horizontal: Literal["left", "center", "right"] = Field(..., description="Horizontal position")
    offset_y: int = Field(0, description="Vertical offset in px")


class AnimationConfig(BaseModel):
    """Animation configuration for captions."""

    enter: str = Field(..., description="Enter animation name")
    exit: str = Field(..., description="Exit animation name")
    enter_duration: float = Field(..., description="Enter duration in seconds")
    exit_duration: float = Field(..., description="Exit duration in seconds")
    scale_emphasis: float = Field(1.0, description="Scale multiplier for emphasis")


class HighlightConfig(BaseModel):
    """Highlight configuration for captions."""

    enabled: bool = Field(..., description="Whether highlighting is enabled")
    trigger: Literal["emphasis", "keywords", "all", "none"] = Field(
        ..., description="What triggers highlighting"
    )
    color: str = Field(..., description="Highlight text color")
    background: str = Field(..., description="Highlight background color")
    scale: float = Field(1.0, description="Scale multiplier for highlighted words")
    animation: str = Field(..., description="Highlight animation name")


class CaptionStyle(BaseModel):
    """Complete caption style configuration."""

    name: str = Field(..., description="Style identifier")
    display_name: str = Field(..., description="Human-readable name")
    description: str = Field(..., description="Description of style")
    display_mode: Literal["word_by_word", "phrase_by_phrase", "line_by_line", "full_sentence"] = (
        Field(..., description="Caption display mode")
    )
    words_per_burst: int | None = Field(
        default=None, description="Words per burst (for word_by_word)"
    )
    words_per_phrase: int | None = Field(
        default=None, description="Words per phrase (for phrase_by_phrase)"
    )
    words_per_line: int | None = Field(
        default=None, description="Words per line (for line_by_line)"
    )
    words_per_sentence: int | None = Field(
        default=None, description="Words per sentence (for full_sentence)"
    )
    word_duration: float | None = Field(default=None, description="Duration per word in seconds")
    phrase_duration: float | None = Field(
        default=None, description="Duration per phrase in seconds"
    )
    line_duration: float | None = Field(default=None, description="Duration per line in seconds")
    sentence_duration: float | None = Field(
        default=None, description="Duration per sentence in seconds"
    )
    gap_duration: float = Field(..., description="Gap between captions in seconds")
    typography: TypographyConfig
    colors: ColorsConfig
    background: BackgroundConfig
    position: PositionConfig
    animation: AnimationConfig
    highlight: HighlightConfig
    platform_optimized: list[str] = Field(..., description="Platforms optimized for")
    recommended_tempo: str = Field(..., description="Recommended tempo token")


# ============================================================================
# CAPTION STYLE PRESETS
# ============================================================================

CAPTION_STYLES: dict[str, CaptionStyle] = {
    # MrBeast / Ali Abdaal - Burst Caption Style
    "burst": CaptionStyle(
        name="burst",
        display_name="Burst Captions",
        description="Word-by-word burst captions (MrBeast, Ali Abdaal style)",
        display_mode="word_by_word",
        words_per_burst=1,
        word_duration=0.3,
        gap_duration=0.05,
        typography=TypographyConfig(
            font_family=["Montserrat", "Impact", "Arial Black", "sans-serif"],
            font_weight=900,
            font_size=72,
            text_transform="uppercase",
            letter_spacing="0.05em",
            line_height=1.2,
        ),
        colors=ColorsConfig(
            text="#ffffff",
            stroke="#000000",
            stroke_width=8,
            shadow="0 4px 8px rgba(0,0,0,0.8)",
        ),
        background=BackgroundConfig(
            enabled=True,
            style="pill",
            color="rgba(0, 0, 0, 0.8)",
            padding="8px 24px",
            border_radius="1000px",
            blur=0,
        ),
        position=PositionConfig(
            vertical="center",
            horizontal="center",
            offset_y=0,
        ),
        animation=AnimationConfig(
            enter="scale_in",
            exit="scale_out",
            enter_duration=0.15,
            exit_duration=0.1,
            scale_emphasis=1.15,
        ),
        highlight=HighlightConfig(
            enabled=True,
            trigger="emphasis",
            color="#ffff00",
            background="rgba(255, 255, 0, 0.3)",
            scale=1.2,
            animation="bounce",
        ),
        platform_optimized=["tiktok", "youtube_shorts", "instagram_reel"],
        recommended_tempo="fast",
    ),
    # Kurzgesagt - Precise Sync Captions
    "precise": CaptionStyle(
        name="precise",
        display_name="Precise Sync",
        description="Precisely timed full-line captions (Kurzgesagt style)",
        display_mode="phrase_by_phrase",
        words_per_phrase=5,
        phrase_duration=2.5,
        gap_duration=0.2,
        typography=TypographyConfig(
            font_family=["Lato", "Open Sans", "sans-serif"],
            font_weight=700,
            font_size=42,
            text_transform="none",
            letter_spacing="0.02em",
            line_height=1.4,
        ),
        colors=ColorsConfig(
            text="#ffffff",
            stroke="#000000",
            stroke_width=3,
            shadow="0 2px 4px rgba(0,0,0,0.5)",
        ),
        background=BackgroundConfig(
            enabled=True,
            style="box",
            color="rgba(0, 0, 0, 0.85)",
            padding="12px 24px",
            border_radius="8px",
            blur=4,
        ),
        position=PositionConfig(
            vertical="bottom",
            horizontal="center",
            offset_y=120,
        ),
        animation=AnimationConfig(
            enter="fade_up",
            exit="fade_out",
            enter_duration=0.3,
            exit_duration=0.2,
            scale_emphasis=1.0,
        ),
        highlight=HighlightConfig(
            enabled=True,
            trigger="keywords",
            color="#ffd700",
            background="none",
            scale=1.0,
            animation="none",
        ),
        platform_optimized=["youtube_long_form", "presentation"],
        recommended_tempo="medium",
    ),
    # LinkedIn - Professional Headline Captions
    "headline": CaptionStyle(
        name="headline",
        display_name="Headline Blocks",
        description="Bold headline-style caption blocks (LinkedIn style)",
        display_mode="line_by_line",
        words_per_line=6,
        line_duration=3.0,
        gap_duration=0.3,
        typography=TypographyConfig(
            font_family=["Inter", "SF Pro Display", "system-ui", "sans-serif"],
            font_weight=800,
            font_size=56,
            text_transform="uppercase",
            letter_spacing="0.03em",
            line_height=1.3,
        ),
        colors=ColorsConfig(
            text="#ffffff",
            stroke=None,
            stroke_width=0,
            shadow="0 8px 16px rgba(0,0,0,0.4)",
        ),
        background=BackgroundConfig(
            enabled=True,
            style="gradient",
            color="linear-gradient(135deg, rgba(79, 70, 229, 0.9), rgba(139, 92, 246, 0.9))",
            padding="16px 32px",
            border_radius="12px",
            blur=0,
        ),
        position=PositionConfig(
            vertical="center",
            horizontal="center",
            offset_y=0,
        ),
        animation=AnimationConfig(
            enter="slide_in_left",
            exit="slide_out_right",
            enter_duration=0.5,
            exit_duration=0.3,
            scale_emphasis=1.0,
        ),
        highlight=HighlightConfig(
            enabled=False,
            trigger="none",
            color="#ffffff",
            background="none",
            scale=1.0,
            animation="none",
        ),
        platform_optimized=["linkedin", "twitter", "instagram_reel"],
        recommended_tempo="medium",
    ),
    # Minimal / Subtle - Clean Professional
    "minimal": CaptionStyle(
        name="minimal",
        display_name="Minimal Clean",
        description="Minimal, clean captions for professional content",
        display_mode="full_sentence",
        words_per_sentence=12,
        sentence_duration=4.0,
        gap_duration=0.5,
        typography=TypographyConfig(
            font_family=["Inter", "system-ui", "sans-serif"],
            font_weight=600,
            font_size=36,
            text_transform="none",
            letter_spacing="0.01em",
            line_height=1.5,
        ),
        colors=ColorsConfig(
            text="#f8fafc",
            stroke=None,
            stroke_width=0,
            shadow="0 2px 8px rgba(0,0,0,0.3)",
        ),
        background=BackgroundConfig(
            enabled=True,
            style="box",
            color="rgba(15, 23, 42, 0.7)",
            padding="10px 20px",
            border_radius="6px",
            blur=8,
        ),
        position=PositionConfig(
            vertical="bottom",
            horizontal="center",
            offset_y=100,
        ),
        animation=AnimationConfig(
            enter="fade_in",
            exit="fade_out",
            enter_duration=0.4,
            exit_duration=0.3,
            scale_emphasis=1.0,
        ),
        highlight=HighlightConfig(
            enabled=False,
            trigger="none",
            color="#ffffff",
            background="none",
            scale=1.0,
            animation="none",
        ),
        platform_optimized=["youtube_long_form", "presentation", "linkedin"],
        recommended_tempo="slow",
    ),
    # Neon / Gaming - High Energy
    "neon": CaptionStyle(
        name="neon",
        display_name="Neon Gaming",
        description="High-energy neon captions for gaming/tech content",
        display_mode="word_by_word",
        words_per_burst=2,
        word_duration=0.4,
        gap_duration=0.1,
        typography=TypographyConfig(
            font_family=["Orbitron", "Rajdhani", "sans-serif"],
            font_weight=800,
            font_size=64,
            text_transform="uppercase",
            letter_spacing="0.1em",
            line_height=1.2,
        ),
        colors=ColorsConfig(
            text="#00ff9f",
            stroke="#00ff9f",
            stroke_width=2,
            shadow="0 0 20px #00ff9f, 0 0 40px #00ff9f",
        ),
        background=BackgroundConfig(
            enabled=True,
            style="box",
            color="rgba(0, 0, 0, 0.9)",
            padding="12px 24px",
            border_radius="4px",
            blur=0,
            border="2px solid #00ff9f",
        ),
        position=PositionConfig(
            vertical="top",
            horizontal="center",
            offset_y=120,
        ),
        animation=AnimationConfig(
            enter="zoom_in",
            exit="zoom_out",
            enter_duration=0.2,
            exit_duration=0.15,
            scale_emphasis=1.3,
        ),
        highlight=HighlightConfig(
            enabled=True,
            trigger="emphasis",
            color="#ff0080",
            background="none",
            scale=1.4,
            animation="pulse",
        ),
        platform_optimized=["tiktok", "youtube_shorts", "twitch"],
        recommended_tempo="sprint",
    ),
    # Vintage / Documentary
    "classic": CaptionStyle(
        name="classic",
        display_name="Classic Documentary",
        description="Classic documentary-style captions",
        display_mode="full_sentence",
        words_per_sentence=15,
        sentence_duration=5.0,
        gap_duration=0.8,
        typography=TypographyConfig(
            font_family=["Georgia", "Times New Roman", "serif"],
            font_weight=400,
            font_size=38,
            text_transform="none",
            letter_spacing="0em",
            line_height=1.6,
        ),
        colors=ColorsConfig(
            text="#f5f5dc",
            stroke=None,
            stroke_width=0,
            shadow="2px 2px 4px rgba(0,0,0,0.8)",
        ),
        background=BackgroundConfig(
            enabled=False,
            style="none",
            color="transparent",
            padding="0",
            border_radius="0",
            blur=0,
        ),
        position=PositionConfig(
            vertical="bottom",
            horizontal="center",
            offset_y=80,
        ),
        animation=AnimationConfig(
            enter="fade_in",
            exit="fade_out",
            enter_duration=0.8,
            exit_duration=0.6,
            scale_emphasis=1.0,
        ),
        highlight=HighlightConfig(
            enabled=False,
            trigger="none",
            color="#ffffff",
            background="none",
            scale=1.0,
            animation="none",
        ),
        platform_optimized=["youtube_long_form", "presentation"],
        recommended_tempo="cinematic",
    ),
}


# ============================================================================
# CAPTION UTILITIES
# ============================================================================


def get_caption_style(name: str) -> CaptionStyle:
    """Get a caption style by name, fallback to minimal if not found."""
    return CAPTION_STYLES.get(name, CAPTION_STYLES["minimal"])


def get_style_for_platform(platform: str) -> str:
    """Get recommended caption style for a platform."""
    platform_map = {
        "tiktok": "burst",
        "youtube_shorts": "burst",
        "instagram_reel": "headline",
        "instagram_story": "burst",
        "youtube_long_form": "precise",
        "linkedin": "headline",
        "twitter": "headline",
        "presentation": "minimal",
        "twitch": "neon",
    }
    return platform_map.get(platform, "minimal")


def list_caption_styles() -> list[dict[str, str]]:
    """List all available caption styles."""
    return [
        {
            "name": style.name,
            "display_name": style.display_name,
            "description": style.description,
            "display_mode": style.display_mode,
            "recommended_tempo": style.recommended_tempo,
        }
        for style in CAPTION_STYLES.values()
    ]
