"""
SiteTemplate Pydantic schemas — PRD-010 Templates Management.
"""

import re
from datetime import datetime
from typing import Annotated, Dict, List, Optional

from pydantic import BaseModel, Field, field_validator, model_validator

# Template variable keys: alphanumeric + underscore, max 64 chars.
_VAR_KEY_RE = re.compile(r"^[a-zA-Z_]\w{0,63}$")


def _validate_hex_color(value: Optional[str]) -> Optional[str]:
    """Validate that a string is a 7-character hex color (#RRGGBB)."""
    if value is None:
        return value
    if not isinstance(value, str) or not value.startswith("#") or len(value) != 7:
        raise ValueError("Color must be a 7-character hex string, e.g. #28B4ED")
    hex_part = value[1:]
    if not all(c in "0123456789abcdefABCDEF" for c in hex_part):
        raise ValueError("Color must be a valid hex color, e.g. #28B4ED")
    return value


# ─── Response schemas ────────────────────────────────────────────────────────


class SiteTemplateSchema(BaseModel):
    """Full template detail — used for single-record responses."""

    id: int
    template_key: str
    template_name: str
    description: Optional[str] = None
    channel: str
    template_type: str
    subject: Optional[str] = None
    body_html: Optional[str] = None
    body_text: Optional[str] = None
    primary_color: str
    accent_color: str
    text_color: str
    variables: List[str]
    is_active: bool
    created_at: datetime
    updated_at: Optional[datetime] = None
    deleted_at: Optional[datetime] = None

    model_config = {"from_attributes": True}


class SiteTemplateListItemSchema(BaseModel):
    """Lighter projection used by the paginated list endpoint."""

    id: int
    template_key: str
    template_name: str
    channel: str
    template_type: str
    is_active: bool
    updated_at: Optional[datetime] = None

    model_config = {"from_attributes": True}


# ─── Request schemas ─────────────────────────────────────────────────────────


class SiteTemplateUpdateRequest(BaseModel):
    """Partial update payload — all fields optional."""

    subject: Optional[str] = None
    body_html: Optional[str] = Field(default=None, max_length=500_000)
    body_text: Optional[str] = Field(default=None, max_length=500_000)
    primary_color: Optional[str] = None
    accent_color: Optional[str] = None
    text_color: Optional[str] = None
    is_active: Optional[bool] = None

    @field_validator("primary_color", "accent_color", "text_color", mode="before")
    @classmethod
    def validate_hex_colors(cls, value: Optional[str]) -> Optional[str]:
        return _validate_hex_color(value)


class TemplatePreviewRequest(BaseModel):
    """Variables dict to substitute into the template at preview time."""

    variables: Dict[str, str] = {}

    @model_validator(mode="after")
    def validate_variables(self) -> "TemplatePreviewRequest":
        if len(self.variables) > 50:
            raise ValueError("variables dict may not contain more than 50 entries")
        for key, value in self.variables.items():
            if not _VAR_KEY_RE.match(key):
                raise ValueError(
                    f"Invalid variable key '{key}': must start with a letter or "
                    "underscore and contain only alphanumerics/underscores (max 64 chars)"
                )
            if len(value) > 2000:
                raise ValueError(
                    f"Variable '{key}' value exceeds maximum length of 2000 characters"
                )
        return self


class TemplatePreviewResponse(BaseModel):
    """Result of a template preview render."""

    html: str
    text: str
    undefined_variables: List[str] = []


class VariableRegistryResponse(BaseModel):
    """Map of template_key → list of expected variable names."""

    registry: Dict[str, List[str]]


class PaginatedTemplatesResponse(BaseModel):
    """Paginated list wrapper."""

    items: List[SiteTemplateListItemSchema]
    total: int
    page: int
    page_size: int
