"""Picture source schemas — discriminated unions per stream type."""

from datetime import datetime
from typing import Annotated, List, Literal, Optional, Union

from pydantic import BaseModel, Discriminator, Field, Tag

# =====================================================================
# Response schemas (per-type, discriminated union)
# =====================================================================


class _PictureSourceResponseBase(BaseModel):
    """Shared fields for all picture source responses."""

    id: str = Field(description="Stream ID")
    name: str = Field(description="Stream name")
    description: Optional[str] = Field(None, description="Stream description")
    tags: List[str] = Field(default_factory=list, description="User-defined tags")
    created_at: datetime = Field(description="Creation timestamp")
    updated_at: datetime = Field(description="Last update timestamp")


class RawPictureSourceResponse(_PictureSourceResponseBase):
    stream_type: Literal["raw"] = "raw"
    display_index: int = Field(description="Display index")
    capture_template_id: str = Field(description="Capture template ID")
    target_fps: int = Field(description="Target FPS")


class ProcessedPictureSourceResponse(_PictureSourceResponseBase):
    stream_type: Literal["processed"] = "processed"
    source_stream_id: str = Field(description="Source stream ID")
    postprocessing_template_id: str = Field(description="Postprocessing template ID")


class StaticImagePictureSourceResponse(_PictureSourceResponseBase):
    stream_type: Literal["static_image"] = "static_image"
    image_asset_id: Optional[str] = Field(None, description="Image asset ID")


class VideoPictureSourceResponse(_PictureSourceResponseBase):
    stream_type: Literal["video"] = "video"
    video_asset_id: Optional[str] = Field(None, description="Video asset ID")
    loop: bool = Field(True, description="Loop video playback")
    playback_speed: float = Field(1.0, description="Playback speed multiplier")
    start_time: Optional[float] = Field(None, description="Trim start time in seconds")
    end_time: Optional[float] = Field(None, description="Trim end time in seconds")
    resolution_limit: Optional[int] = Field(None, description="Max width for decode")
    clock_id: Optional[str] = Field(None, description="Sync clock ID")
    target_fps: int = Field(30, description="Target FPS")


PictureSourceResponse = Annotated[
    Union[
        Annotated[RawPictureSourceResponse, Tag("raw")],
        Annotated[ProcessedPictureSourceResponse, Tag("processed")],
        Annotated[StaticImagePictureSourceResponse, Tag("static_image")],
        Annotated[VideoPictureSourceResponse, Tag("video")],
    ],
    Discriminator("stream_type"),
]

# =====================================================================
# Create schemas (per-type, discriminated union)
# =====================================================================


class _PictureSourceCreateBase(BaseModel):
    """Shared fields for all picture source create requests."""

    name: str = Field(description="Stream name", min_length=1, max_length=100)
    description: Optional[str] = Field(None, description="Stream description", max_length=500)
    tags: List[str] = Field(default_factory=list, description="User-defined tags")


class RawPictureSourceCreate(_PictureSourceCreateBase):
    stream_type: Literal["raw"] = "raw"
    display_index: int = Field(description="Display index", ge=0)
    capture_template_id: str = Field(description="Capture template ID")
    target_fps: int = Field(30, description="Target FPS", ge=1, le=90)


class ProcessedPictureSourceCreate(_PictureSourceCreateBase):
    stream_type: Literal["processed"] = "processed"
    source_stream_id: str = Field(description="Source stream ID")
    postprocessing_template_id: str = Field(description="Postprocessing template ID")


class StaticImagePictureSourceCreate(_PictureSourceCreateBase):
    stream_type: Literal["static_image"] = "static_image"
    image_asset_id: str = Field(description="Image asset ID")


class VideoPictureSourceCreate(_PictureSourceCreateBase):
    stream_type: Literal["video"] = "video"
    video_asset_id: str = Field(description="Video asset ID")
    loop: bool = Field(True, description="Loop video playback")
    playback_speed: float = Field(1.0, description="Playback speed multiplier", ge=0.1, le=10.0)
    start_time: Optional[float] = Field(None, description="Trim start time in seconds", ge=0)
    end_time: Optional[float] = Field(None, description="Trim end time in seconds", ge=0)
    resolution_limit: Optional[int] = Field(
        None, description="Max width in pixels for decode downscale", ge=64, le=7680
    )
    clock_id: Optional[str] = Field(None, description="Sync clock ID for frame-accurate timing")
    target_fps: int = Field(30, description="Target FPS", ge=1, le=90)


PictureSourceCreate = Annotated[
    Union[
        Annotated[RawPictureSourceCreate, Tag("raw")],
        Annotated[ProcessedPictureSourceCreate, Tag("processed")],
        Annotated[StaticImagePictureSourceCreate, Tag("static_image")],
        Annotated[VideoPictureSourceCreate, Tag("video")],
    ],
    Discriminator("stream_type"),
]

# =====================================================================
# Update schemas (per-type, discriminated union)
# =====================================================================


class _PictureSourceUpdateBase(BaseModel):
    """Shared fields for all picture source update requests."""

    name: Optional[str] = Field(None, description="Stream name", min_length=1, max_length=100)
    description: Optional[str] = Field(None, description="Stream description", max_length=500)
    tags: Optional[List[str]] = None


class RawPictureSourceUpdate(_PictureSourceUpdateBase):
    stream_type: Literal["raw"] = "raw"
    display_index: Optional[int] = Field(None, description="Display index", ge=0)
    capture_template_id: Optional[str] = Field(None, description="Capture template ID")
    target_fps: Optional[int] = Field(None, description="Target FPS", ge=1, le=90)


class ProcessedPictureSourceUpdate(_PictureSourceUpdateBase):
    stream_type: Literal["processed"] = "processed"
    source_stream_id: Optional[str] = Field(None, description="Source stream ID")
    postprocessing_template_id: Optional[str] = Field(
        None, description="Postprocessing template ID"
    )


class StaticImagePictureSourceUpdate(_PictureSourceUpdateBase):
    stream_type: Literal["static_image"] = "static_image"
    image_asset_id: Optional[str] = Field(None, description="Image asset ID")


class VideoPictureSourceUpdate(_PictureSourceUpdateBase):
    stream_type: Literal["video"] = "video"
    video_asset_id: Optional[str] = Field(None, description="Video asset ID")
    loop: Optional[bool] = Field(None, description="Loop video playback")
    playback_speed: Optional[float] = Field(
        None, description="Playback speed multiplier", ge=0.1, le=10.0
    )
    start_time: Optional[float] = Field(None, description="Trim start time in seconds", ge=0)
    end_time: Optional[float] = Field(None, description="Trim end time in seconds", ge=0)
    resolution_limit: Optional[int] = Field(
        None, description="Max width in pixels for decode downscale", ge=64, le=7680
    )
    clock_id: Optional[str] = Field(None, description="Sync clock ID for frame-accurate timing")
    target_fps: Optional[int] = Field(None, description="Target FPS", ge=1, le=90)


PictureSourceUpdate = Annotated[
    Union[
        Annotated[RawPictureSourceUpdate, Tag("raw")],
        Annotated[ProcessedPictureSourceUpdate, Tag("processed")],
        Annotated[StaticImagePictureSourceUpdate, Tag("static_image")],
        Annotated[VideoPictureSourceUpdate, Tag("video")],
    ],
    Discriminator("stream_type"),
]

# =====================================================================
# List response
# =====================================================================


class PictureSourceListResponse(BaseModel):
    """List of picture sources response."""

    streams: List[PictureSourceResponse] = Field(description="List of picture sources")
    count: int = Field(description="Number of streams")


# =====================================================================
# Test / Validation (unchanged)
# =====================================================================


class PictureSourceTestRequest(BaseModel):
    """Request to test a picture source."""

    capture_duration: float = Field(
        default=5.0,
        ge=0.0,
        le=30.0,
        description="Duration to capture in seconds (0 = single frame)",
    )
    border_width: int = Field(
        default=10, ge=1, le=100, description="Border width in pixels for preview"
    )


class ImageValidateRequest(BaseModel):
    """Request to validate an image source (URL or file path)."""

    image_source: str = Field(description="Image URL or local file path")


class ImageValidateResponse(BaseModel):
    """Response from image validation."""

    valid: bool = Field(description="Whether the image source is accessible and valid")
    width: Optional[int] = Field(None, description="Image width in pixels")
    height: Optional[int] = Field(None, description="Image height in pixels")
    preview: Optional[str] = Field(None, description="Base64-encoded JPEG thumbnail")
    error: Optional[str] = Field(None, description="Error message if invalid")
