"""Publishing / SEO / PWA DTOs — Phase 11.7."""
from __future__ import annotations

from datetime import datetime
from uuid import UUID

from pydantic import BaseModel, ConfigDict, Field

from app.models.types import (
    DomainEdgeStatus,
    PublishReleaseStatus,
    PublishTarget,
    PwaStatus,
    RobotsStatus,
    SeoStatus,
    SeoTarget,
    SitemapStatus,
)
from app.schemas.common import ORMBase

_FORBID = ConfigDict(extra="forbid")


class PublishReleaseCreate(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    target_type: PublishTarget
    target_id: UUID
    notes: str | None = None
    metadata_json: dict | None = None


class PublishReleaseUpdate(BaseModel):
    model_config = _FORBID

    status: PublishReleaseStatus | None = None
    notes: str | None = None
    error_message: str | None = None
    metadata_json: dict | None = None
    version: int = Field(ge=1)


class PublishReleaseRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    target_type: PublishTarget
    target_id: UUID
    status: PublishReleaseStatus
    notes: str | None
    error_message: str | None
    completed_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 PublishReleaseListResponse(BaseModel):
    items: list[PublishReleaseRead]
    total: int
    page: int
    page_size: int


class DomainEdgeBindingCreate(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    site_id: UUID
    site_domain_id: UUID
    dns_status_ref: str | None = Field(default=None, max_length=255)
    ssl_cert_ref: str | None = Field(default=None, max_length=255)
    edge_map_ref: str | None = Field(default=None, max_length=255)
    status: DomainEdgeStatus = DomainEdgeStatus.PENDING
    metadata_json: dict | None = None


class DomainEdgeBindingUpdate(BaseModel):
    model_config = _FORBID

    status: DomainEdgeStatus | None = None
    dns_status_ref: str | None = Field(default=None, max_length=255)
    ssl_cert_ref: str | None = Field(default=None, max_length=255)
    edge_map_ref: str | None = Field(default=None, max_length=255)
    metadata_json: dict | None = None
    version: int = Field(ge=1)


class DomainEdgeBindingRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    site_id: UUID
    site_domain_id: UUID
    host: str
    status: DomainEdgeStatus
    dns_status_ref: str | None
    ssl_cert_ref: str | None
    edge_map_ref: str | 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 DomainEdgeBindingListResponse(BaseModel):
    items: list[DomainEdgeBindingRead]
    total: int
    page: int
    page_size: int


class SeoMetadataUpsert(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    target_type: SeoTarget
    target_id: UUID
    status: SeoStatus = SeoStatus.DRAFT
    title: str | None = Field(default=None, max_length=255)
    description: str | None = None
    canonical_url: str | None = Field(default=None, max_length=500)
    robots_directive: str | None = Field(default=None, max_length=100)
    og_json: dict | None = None
    metadata_json: dict | None = None
    version: int | None = Field(default=None, ge=1)


class SeoMetadataUpdate(BaseModel):
    model_config = _FORBID

    status: SeoStatus | None = None
    title: str | None = Field(default=None, max_length=255)
    description: str | None = None
    canonical_url: str | None = Field(default=None, max_length=500)
    robots_directive: str | None = Field(default=None, max_length=100)
    og_json: dict | None = None
    metadata_json: dict | None = None
    version: int = Field(ge=1)


class SeoMetadataRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    target_type: SeoTarget
    target_id: UUID
    status: SeoStatus
    title: str | None
    description: str | None
    canonical_url: str | None
    robots_directive: str | None
    og_json: dict | 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 SeoMetadataListResponse(BaseModel):
    items: list[SeoMetadataRead]
    total: int
    page: int
    page_size: int


class SitemapShellUpsert(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    site_id: UUID
    status: SitemapStatus = SitemapStatus.DRAFT
    entries_json: dict | None = None
    storage_file_ref: str | None = Field(default=None, max_length=255)
    metadata_json: dict | None = None
    version: int | None = Field(default=None, ge=1)


class SitemapShellUpdate(BaseModel):
    model_config = _FORBID

    status: SitemapStatus | None = None
    entries_json: dict | None = None
    storage_file_ref: str | None = Field(default=None, max_length=255)
    metadata_json: dict | None = None
    version: int = Field(ge=1)


class SitemapShellRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    site_id: UUID
    status: SitemapStatus
    entries_json: dict | None
    storage_file_ref: str | 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 SitemapShellListResponse(BaseModel):
    items: list[SitemapShellRead]
    total: int
    page: int
    page_size: int


class RobotsShellUpsert(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    site_id: UUID
    status: RobotsStatus = RobotsStatus.DRAFT
    content_text: str | None = None
    rules_json: dict | None = None
    metadata_json: dict | None = None
    version: int | None = Field(default=None, ge=1)


class RobotsShellUpdate(BaseModel):
    model_config = _FORBID

    status: RobotsStatus | None = None
    content_text: str | None = None
    rules_json: dict | None = None
    metadata_json: dict | None = None
    version: int = Field(ge=1)


class RobotsShellRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    site_id: UUID
    status: RobotsStatus
    content_text: str | None
    rules_json: dict | 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 RobotsShellListResponse(BaseModel):
    items: list[RobotsShellRead]
    total: int
    page: int
    page_size: int


class PwaManifestUpsert(BaseModel):
    model_config = _FORBID

    workspace_id: UUID
    site_id: UUID
    status: PwaStatus = PwaStatus.DRAFT
    name: str | None = Field(default=None, max_length=255)
    short_name: str | None = Field(default=None, max_length=100)
    start_url: str | None = Field(default=None, max_length=500)
    manifest_json: dict | None = None
    service_worker_ref: str | None = Field(default=None, max_length=255)
    metadata_json: dict | None = None
    version: int | None = Field(default=None, ge=1)


class PwaManifestUpdate(BaseModel):
    model_config = _FORBID

    status: PwaStatus | None = None
    name: str | None = Field(default=None, max_length=255)
    short_name: str | None = Field(default=None, max_length=100)
    start_url: str | None = Field(default=None, max_length=500)
    manifest_json: dict | None = None
    service_worker_ref: str | None = Field(default=None, max_length=255)
    metadata_json: dict | None = None
    version: int = Field(ge=1)


class PwaManifestRead(ORMBase):
    id: UUID
    tenant_id: UUID
    workspace_id: UUID
    site_id: UUID
    status: PwaStatus
    name: str | None
    short_name: str | None
    start_url: str | None
    manifest_json: dict | None
    service_worker_ref: str | 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 PwaManifestListResponse(BaseModel):
    items: list[PwaManifestRead]
    total: int
    page: int
    page_size: int
