"""Templates domain — request/response schemas."""
from __future__ import annotations

from datetime import datetime
from typing import Optional
from uuid import UUID

from pydantic import BaseModel, Field


class TemplateCreate(BaseModel):
    """Admin: register a new template."""

    name: str = Field(..., min_length=1, max_length=120)
    ref: str = Field(
        ..., min_length=1, max_length=63,
        description="Stable slug used as the subdomain label and CF Pages project_ref (e.g. 'tpl001').",
        pattern=r"^[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$|^[a-z0-9]$",
    )
    description: Optional[str] = None
    thumbnail_url: Optional[str] = None
    tags: Optional[list[str]] = None
    github_repo: str = Field(
        ..., description="Private GitHub repo in owner/repo format (e.g. 'myorg/my-template')."
    )
    github_installation_id: int = Field(
        0, description="GitHub App installation ID. 0 = use platform default from settings."
    )
    framework: str = Field("react_app", description="react_app | nuxt_app | html")
    main_branch: str = "main"
    dev_branch: str = "development"
    starter_branch: str = "starter"
    # Subdomains default to ref / dev-{ref} if omitted.
    demo_subdomain: Optional[str] = Field(
        None, description="Demo subdomain label. Defaults to ref."
    )
    dev_subdomain: Optional[str] = Field(
        None, description="Dev demo subdomain label. Defaults to 'dev-{ref}'."
    )
    is_active: bool = False
    is_default: bool = Field(
        False,
        description="Default starter for this framework when project creation does not provide a template.",
    )
    is_showcased: bool = Field(
        False,
        description="Whether this live template is listed on the public marketing site.",
    )
    showcase_rank: Optional[int] = Field(
        None, ge=0, description="Public showcase order. Lower values appear first."
    )
    plan_slugs: list[str] = Field(
        default_factory=list,
        description="Plan slugs that may use this template. Empty = all plans.",
    )


class TemplateBootstrapCreate(BaseModel):
    """Admin: create a GitHub-backed starter template from Core policy."""

    template_ref: str = Field(
        ..., min_length=1, max_length=63,
        description="Stable template slug. Also becomes the production demo subdomain.",
        pattern=r"^[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$|^[a-z0-9]$",
    )
    name: str = Field(..., min_length=1, max_length=120)
    framework: str = Field("react_app", description="react_app | nuxt_app | html")
    branch: str = Field("starter", description="Starter branch copied into user projects.")
    description: Optional[str] = None
    thumbnail_url: Optional[str] = None
    tags: Optional[list[str]] = None
    github_repo_name: Optional[str] = Field(
        None,
        description="Optional repo name. Defaults to p2hs-template-{template_ref}.",
    )
    github_installation_id: int = Field(
        0, description="GitHub App installation ID. 0 = use template/platform default."
    )
    is_default: bool = False
    is_active: bool = True
    is_showcased: bool = False
    showcase_rank: Optional[int] = Field(None, ge=0)
    plan_slugs: list[str] = Field(default_factory=list)


class TemplateBootstrapResponse(BaseModel):
    template_id: UUID
    template_ref: str
    github_repo: str
    github_repo_url: Optional[str] = None
    main_branch: str
    dev_branch: str
    starter_branch: str
    starter_sha: Optional[str] = None
    demo_url: str
    dev_url: str
    deploy_status: str
    production_deploy_enqueued: bool = False
    development_deploy_enqueued: bool = False


class TemplateUpdate(BaseModel):
    """Admin: update an existing template."""

    name: Optional[str] = Field(None, min_length=1, max_length=120)
    description: Optional[str] = None
    thumbnail_url: Optional[str] = None
    tags: Optional[list[str]] = None
    framework: Optional[str] = None
    main_branch: Optional[str] = None
    dev_branch: Optional[str] = None
    starter_branch: Optional[str] = None
    is_active: Optional[bool] = None
    is_default: Optional[bool] = None
    is_showcased: Optional[bool] = None
    showcase_rank: Optional[int] = Field(None, ge=0)
    plan_slugs: Optional[list[str]] = Field(
        None, description="Replaces the full plan-access list. None = no change."
    )


class TemplatePlanAccessItem(BaseModel):
    plan_slug: str


class TemplateResponse(BaseModel):
    id: UUID
    name: str
    ref: str
    description: Optional[str]
    thumbnail_url: Optional[str]
    tags: Optional[list[str]]
    github_repo: str
    framework: str
    main_branch: str
    dev_branch: str
    starter_branch: str
    starter_sha: Optional[str]
    demo_subdomain: str
    dev_subdomain: str
    demo_url: Optional[str]
    dev_url: Optional[str]
    deploy_status: str
    is_active: bool
    is_default: bool
    is_showcased: bool
    showcase_rank: Optional[int]
    plan_slugs: list[str]
    created_at: datetime
    updated_at: datetime
    model_config = {"from_attributes": True}


class TemplateListResponse(BaseModel):
    items: list[TemplateResponse]
    total: int


class PublicTemplateResponse(BaseModel):
    """Safe, marketing-facing template data for anonymous visitors."""

    name: str
    ref: str
    description: Optional[str]
    thumbnail_url: Optional[str]
    tags: Optional[list[str]]
    framework: str
    demo_url: str


class PublicTemplateListResponse(BaseModel):
    items: list[PublicTemplateResponse]
    total: int


class TemplateDeployResponse(BaseModel):
    template_id: UUID
    ref: str
    environment: str  # "production" | "development"
    status: str
    message: Optional[str] = None
