"""Schémas Pydantic du module Sites (spec 2026-08-31 §5)."""

import uuid
from datetime import datetime
from typing import Annotated, Literal

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

# Garde-fou anti-abus (décision §10.3) : constante applicative, pas de contrainte SQL.
MAX_TARGETS_PER_SITE = 20

CountryCode = Annotated[str, StringConstraints(pattern=r"^[A-Z]{2}$")]  # ISO 3166-1 alpha-2
LanguageCode = Annotated[str, StringConstraints(pattern=r"^[a-z]{2}$")]  # ISO 639-1


class TargetIn(BaseModel):
    country: CountryCode
    language: LanguageCode
    is_default: bool = False


class SiteCreate(BaseModel):
    domain: Annotated[str, StringConstraints(min_length=1, max_length=300)]
    name: Annotated[str, StringConstraints(min_length=1, max_length=200)] | None = None
    targets: Annotated[list[TargetIn], Field(min_length=1, max_length=MAX_TARGETS_PER_SITE)]

    @model_validator(mode="after")
    def _targets_coherent(self) -> "SiteCreate":
        if sum(t.is_default for t in self.targets) != 1:
            raise ValueError("exactement une cible doit être marquée par défaut")
        couples = [(t.country, t.language) for t in self.targets]
        if len(set(couples)) != len(couples):
            raise ValueError("couples (pays, langue) en double dans les cibles")
        return self


class SiteUpdate(BaseModel):
    # Le domaine est immuable : absent de ce schéma, et tout champ inattendu
    # (dont `domain`) est un 422 grâce à extra="forbid".
    model_config = ConfigDict(extra="forbid")

    name: Annotated[str, StringConstraints(min_length=1, max_length=200)]


class TargetCreate(BaseModel):
    country: CountryCode
    language: LanguageCode


class TargetUpdate(BaseModel):
    model_config = ConfigDict(extra="forbid")

    # `false` refusé : on promeut une autre cible, on ne « dé-défaute » pas (spec §5).
    is_default: Literal[True]


class TargetOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: uuid.UUID
    country: str
    language: str
    is_default: bool
    created_at: datetime


class SiteOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: uuid.UUID
    domain: str
    name: str
    created_at: datetime
    updated_at: datetime
    targets: list[TargetOut]


class SiteListOut(BaseModel):
    items: list[SiteOut]
    next_cursor: str | None


class PreflightIn(BaseModel):
    domain: Annotated[str, StringConstraints(min_length=1, max_length=300)]
