from __future__ import annotations

from typing import Any

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

from app.enums.common import (
    VIDEO_SCHEMA_EDITABLE_TEXT_MAX_LEN,
    VIDEO_SCHEMA_FLOW_CONTENT_MAX_LEN,
    VIDEO_SCHEMA_TIME_DESC_MAX_LEN,
    VIDEO_SCHEMA_TIME_STAGE_MAX_LEN,
)
from app.schemas.common import NaiveDatetimeOptional


class VideoPromptSchemaConfigSaveRequest(BaseModel):
    """保存管理后台视频提词 Schema 配置。"""

    model_config = ConfigDict(extra="forbid")

    is_enabled: bool = Field(True, description="是否启用后台自定义配置；关闭后生成时回落默认 CLIENT_SCHEMA_V1")
    data: dict[str, Any] = Field(..., description="管理后台配置数据，包含 sections、time_plan_rules 等。管理字段不会传给 AI")

    @field_validator("data")
    @classmethod
    def _validate_data(cls, value: dict[str, Any]) -> dict[str, Any]:
        if not isinstance(value, dict) or not value:
            raise ValueError("data 必须是非空 JSON 对象")
        return value


class VideoPromptSchemaConfigImportRequest(VideoPromptSchemaConfigSaveRequest):
    """导入 JSON 配置。"""


class VideoPromptSchemaPreviewRequest(BaseModel):
    """预览指定配置在某个视频规格下的运行时 schema。"""

    model_config = ConfigDict(extra="forbid")

    is_enabled: bool = Field(True, description="是否按自定义配置预览；关闭时按默认配置预览")
    data: dict[str, Any] = Field(..., description="待预览的管理后台配置 JSON")
    duration: int = Field(8, ge=1, le=3600, description="视频时长，单位秒")
    aspect_ratio: str = Field("9:16", min_length=1, max_length=16, description="视频比例，例如 9:16")
    resolution: str = Field("1080p", min_length=1, max_length=32, description="清晰度，例如 720p/1080p")
    frame_rate: str = Field("30fps", min_length=1, max_length=32, description="帧率，例如 30fps")
    supported_durations: list[int] = Field(default_factory=list, description="支持时长列表，仅用于预览输出规格限制")
    supported_ratios: list[str] = Field(default_factory=list, description="支持比例列表，仅用于预览输出规格限制")
    supported_resolutions: list[str] = Field(default_factory=list, description="支持分辨率列表，仅用于预览输出规格限制")

    @model_validator(mode="after")
    def _ensure_data(self) -> "VideoPromptSchemaPreviewRequest":
        if not self.data:
            raise ValueError("data 不能为空")
        return self

    def to_video_config(self) -> dict[str, Any]:
        return {
            "duration": self.duration,
            "aspect_ratio": self.aspect_ratio,
            "resolution": self.resolution,
            "frame_rate": self.frame_rate,
            "supported_durations": self.supported_durations,
            "supported_ratios": self.supported_ratios,
            "supported_resolutions": self.supported_resolutions,
        }


class VideoPromptSchemaConfigOut(BaseModel):
    """管理后台视频提词 Schema 配置详情。"""

    id: str | None = Field(None, description="system_configs.id；未保存时为空")
    key: str = Field(..., description="system_configs.key")
    description: str | None = Field(None, description="配置说明")
    is_enabled: bool = Field(False, description="当前是否启用数据库自定义配置")
    using_default: bool = Field(False, description="当前是否正在使用默认 CLIENT_SCHEMA_V1 兜底")
    data: dict[str, Any] = Field(..., description="当前管理后台配置数据")
    default_data: dict[str, Any] = Field(..., description="由 CLIENT_SCHEMA_V1 转换得到的默认配置")
    created_at: NaiveDatetimeOptional = None
    updated_at: NaiveDatetimeOptional = None


class VideoPromptSchemaExportOut(BaseModel):
    version: str
    key: str
    is_enabled: bool
    data: dict[str, Any]


class VideoPromptSchemaPreviewOut(BaseModel):
    schema_config_snapshot: dict[str, Any] = Field(..., description="本次预览使用的配置快照")
    runtime_schema: dict[str, Any] = Field(..., description="传给 AI 的纯运行时 schema，不包含 label/editable/enabled 等管理字段")
    time_plan: list[dict[str, Any]] = Field(default_factory=list, description="根据秒数切片规则生成的动态时间规划")


class VideoPromptSchemaLengthLimitsOut(BaseModel):
    editable_text_max_len: int = VIDEO_SCHEMA_EDITABLE_TEXT_MAX_LEN
    flow_content_max_len: int = VIDEO_SCHEMA_FLOW_CONTENT_MAX_LEN
    time_stage_max_len: int = VIDEO_SCHEMA_TIME_STAGE_MAX_LEN
    time_desc_max_len: int = VIDEO_SCHEMA_TIME_DESC_MAX_LEN
