"""Theme & layout engine DTOs — Phase 11.3."""
from __future__ import annotations

from datetime import datetime
from uuid import UUID

from pydantic import BaseModel, ConfigDict, Field

from app.models.types import (
    DirectionMode,
    LayoutKind,
    LayoutStatus,
    LayoutVersionStatus,
    ThemeStatus,
    ThemeVersionStatus,
)
from app.schemas.common import ORMBase

_FORBID = ConfigDict(extra="forbid")


# --- Themes ---


class ExperienceThemeCreate(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    code: str = Field(max_length=50)
    name: str = Field(max_length=255)
    description: str | None = None
    status: ThemeStatus = ThemeStatus.DRAFT
    direction_mode: DirectionMode = DirectionMode.BOTH
    category: str | None = Field(default=None, max_length=100)
    tags: list[str] | None = None
    metadata_json: dict | None = None


class ExperienceThemeUpdate(BaseModel):
    model_config = _FORBID

    name: str | None = Field(default=None, max_length=255)
    description: str | None = None
    status: ThemeStatus | None = None
    direction_mode: DirectionMode | None = None
    category: str | None = Field(default=None, max_length=100)
    tags: list[str] | None = None
    metadata_json: dict | None = None
    version: int = Field(ge=1)


class ExperienceThemeRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    code: str
    name: str
    description: str | None
    status: ThemeStatus
    direction_mode: DirectionMode
    category: str | None
    tags: list | None
    latest_version_number: int
    published_version_id: UUID | None
    is_system: bool
    metadata_json: dict | None
    version: int
    is_deleted: bool
    created_by: str | None
    updated_by: str | None
    created_at: datetime
    updated_at: datetime


class ExperienceThemeListResponse(BaseModel):
    items: list[ExperienceThemeRead]
    total: int
    page: int
    page_size: int


# --- Theme Versions ---


class ExperienceThemeVersionCreate(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    theme_id: UUID
    tokens: dict | None = None
    brand_shell: dict | None = None
    direction_mode: DirectionMode | None = None
    changelog: str | None = None
    metadata_json: dict | None = None


class ExperienceThemeVersionUpdate(BaseModel):
    model_config = _FORBID

    tokens: dict | None = None
    brand_shell: dict | None = None
    direction_mode: DirectionMode | None = None
    changelog: str | None = None
    metadata_json: dict | None = None
    version: int = Field(ge=1)


class ExperienceThemeVersionRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    theme_id: UUID
    version_number: int
    status: ThemeVersionStatus
    tokens: dict | None
    brand_shell: dict | None
    direction_mode: DirectionMode | None
    changelog: str | None
    is_immutable: bool
    published_at: datetime | None
    retired_at: datetime | None
    metadata_json: dict | None
    version: int
    is_deleted: bool
    created_by: str | None
    updated_by: str | None
    created_at: datetime
    updated_at: datetime


class ExperienceThemeVersionListResponse(BaseModel):
    items: list[ExperienceThemeVersionRead]
    total: int
    page: int
    page_size: int


# --- Layouts ---


class ExperienceLayoutCreate(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    code: str = Field(max_length=50)
    name: str = Field(max_length=255)
    description: str | None = None
    kind: LayoutKind = LayoutKind.PAGE_SHELL
    status: LayoutStatus = LayoutStatus.DRAFT
    direction_mode: DirectionMode = DirectionMode.BOTH
    category: str | None = Field(default=None, max_length=100)
    tags: list[str] | None = None
    metadata_json: dict | None = None


class ExperienceLayoutUpdate(BaseModel):
    model_config = _FORBID

    name: str | None = Field(default=None, max_length=255)
    description: str | None = None
    kind: LayoutKind | None = None
    status: LayoutStatus | None = None
    direction_mode: DirectionMode | None = None
    category: str | None = Field(default=None, max_length=100)
    tags: list[str] | None = None
    metadata_json: dict | None = None
    version: int = Field(ge=1)


class ExperienceLayoutRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    code: str
    name: str
    description: str | None
    kind: LayoutKind
    status: LayoutStatus
    direction_mode: DirectionMode
    category: str | None
    tags: list | None
    latest_version_number: int
    published_version_id: UUID | None
    is_system: bool
    metadata_json: dict | None
    version: int
    is_deleted: bool
    created_by: str | None
    updated_by: str | None
    created_at: datetime
    updated_at: datetime


class ExperienceLayoutListResponse(BaseModel):
    items: list[ExperienceLayoutRead]
    total: int
    page: int
    page_size: int


# --- Layout Versions ---


class ExperienceLayoutVersionCreate(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    layout_id: UUID
    regions: list[dict] | None = None
    structure_shell: dict | None = None
    changelog: str | None = None
    metadata_json: dict | None = None


class ExperienceLayoutVersionUpdate(BaseModel):
    model_config = _FORBID

    regions: list[dict] | None = None
    structure_shell: dict | None = None
    changelog: str | None = None
    metadata_json: dict | None = None
    version: int = Field(ge=1)


class ExperienceLayoutVersionRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    layout_id: UUID
    version_number: int
    status: LayoutVersionStatus
    regions: list | None
    structure_shell: dict | None
    changelog: str | None
    is_immutable: bool
    published_at: datetime | None
    retired_at: datetime | None
    metadata_json: dict | None
    version: int
    is_deleted: bool
    created_by: str | None
    updated_by: str | None
    created_at: datetime
    updated_at: datetime


class ExperienceLayoutVersionListResponse(BaseModel):
    items: list[ExperienceLayoutVersionRead]
    total: int
    page: int
    page_size: int


# --- Site Theme Bindings ---


class SiteThemeBindingCreate(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    site_id: UUID
    theme_id: UUID
    theme_version_id: UUID
    metadata_json: dict | None = None


class SiteThemeBindingUpdate(BaseModel):
    model_config = _FORBID

    metadata_json: dict | None = None
    version: int = Field(ge=1)


class SiteThemeBindingRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    site_id: UUID
    theme_id: UUID
    theme_version_id: UUID
    is_active: bool
    metadata_json: dict | None
    version: int
    is_deleted: bool
    created_by: str | None
    updated_by: str | None
    created_at: datetime
    updated_at: datetime


class SiteThemeBindingListResponse(BaseModel):
    items: list[SiteThemeBindingRead]
    total: int
    page: int
    page_size: int


# --- Page Layout Bindings ---


class PageLayoutBindingCreate(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    site_id: UUID
    page_id: UUID
    layout_id: UUID
    layout_version_id: UUID
    metadata_json: dict | None = None


class PageLayoutBindingUpdate(BaseModel):
    model_config = _FORBID

    metadata_json: dict | None = None
    version: int = Field(ge=1)


class PageLayoutBindingRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    site_id: UUID
    page_id: UUID
    layout_id: UUID
    layout_version_id: UUID
    is_active: bool
    metadata_json: dict | None
    version: int
    is_deleted: bool
    created_by: str | None
    updated_by: str | None
    created_at: datetime
    updated_at: datetime


class PageLayoutBindingListResponse(BaseModel):
    items: list[PageLayoutBindingRead]
    total: int
    page: int
    page_size: int
