"""
Pydantic schemas for CMS Django model JSONFields.

These schemas validate data stored in PostgreSQL JSONB columns for
the CMS models: Site, Page, Component, Block, OutboxItem, etc.

All validation traces back to SST YAML definitions.

Database Models:
    - sites.Site: settings JSONField
    - sites.Page: data, metadata, body JSONFields
    - sites.Component: props JSONField
    - sites.Block: props JSONField
    - workflows.OutboxItem: item_data JSONField
    - agents.AgentAPIKey: permissions JSONField
"""

from typing import Any

from pydantic import Field, field_validator

from lightwave.schema.pydantic.core.base import JSONFieldSchema
from lightwave.schema.pydantic.core.validators import FieldOptions

# =============================================================================
# SITE SETTINGS
# =============================================================================


class BrandSettingsSchema(JSONFieldSchema):
    """Brand configuration within Site.settings."""

    name: str = Field(..., description="Brand display name")
    tagline: str | None = Field(None, description="Brand tagline")
    logo_url: str | None = Field(None, description="Logo URL path")
    favicon_url: str | None = Field(None, description="Favicon URL path")


class AuthSettingsSchema(JSONFieldSchema):
    """Authentication configuration within Site.settings."""

    mode: str = Field("subscription", description="Auth mode: private, ecommerce, subscription")
    show_signup: bool = Field(True, description="Show signup option")
    show_login: bool = Field(True, description="Show login option")
    social_providers: list[str] = Field(default_factory=list, description="Enabled OAuth providers")
    require_email_verification: bool = Field(True, description="Require email verification")


class FeatureSettingsSchema(JSONFieldSchema):
    """Feature flags within Site.settings."""

    use_teams: bool = Field(False, description="Enable team functionality")
    use_subscriptions: bool = Field(False, description="Enable subscription billing")
    use_chat: bool = Field(False, description="Enable AI chat")
    use_shop: bool = Field(False, description="Enable e-commerce")
    use_blog: bool = Field(False, description="Enable blog functionality")


class ThemeSettingsSchema(JSONFieldSchema):
    """Theme configuration within Site.settings."""

    brand_color: str = Field("blue", description="Primary brand color")
    dark_mode: bool = Field(False, description="Enable dark mode by default")
    custom_css: str | None = Field(None, description="Custom CSS overrides")


class SiteSettingsSchema(JSONFieldSchema):
    """
    Schema for Site.settings JSONField.

    Validates the complete site configuration.
    """

    brand: BrandSettingsSchema | None = Field(None, description="Brand settings")
    auth: AuthSettingsSchema | None = Field(None, description="Auth settings")
    features: FeatureSettingsSchema | None = Field(None, description="Feature flags")
    theme: ThemeSettingsSchema | None = Field(None, description="Theme settings")
    # Allow arbitrary additional settings
    extra: dict[str, Any] = Field(default_factory=dict, description="Additional settings")


# =============================================================================
# PAGE METADATA (SEO)
# =============================================================================


class PageMetadataSchema(JSONFieldSchema):
    """
    Schema for Page.metadata JSONField.

    SEO and social sharing metadata.
    """

    title: str | None = Field(None, description="Custom <title> tag (overrides page.title)")
    description: str | None = Field(None, description="Meta description for SEO")
    og_image: str | None = Field(None, description="Open Graph image URL")
    og_title: str | None = Field(None, description="Open Graph title (overrides title)")
    og_description: str | None = Field(None, description="Open Graph description")
    robots: str | None = Field(None, description="Robots directive (e.g., 'noindex, nofollow')")
    canonical_url: str | None = Field(None, description="Canonical URL if different from path")
    structured_data: dict[str, Any] | None = Field(None, description="JSON-LD structured data")


# =============================================================================
# PAGE BODY (CONTENT BLOCKS)
# =============================================================================


class PageBlockReferenceSchema(JSONFieldSchema):
    """Reference to a reusable Block within page body."""

    block_id: int = Field(..., description="ID of the Block model instance")
    order: int = Field(..., description="Position in page body")


class InlineBlockSchema(JSONFieldSchema):
    """Inline block definition within page body (not a reference)."""

    block_type: str = Field(..., description="Block type (paragraph, heading, image, etc.)")
    props: dict[str, Any] = Field(default_factory=dict, description="Block properties")
    order: int = Field(..., description="Position in page body")


# =============================================================================
# OUTBOX ITEM DATA (POLYMORPHIC)
# =============================================================================


class PageCreationPayloadSchema(JSONFieldSchema):
    """OutboxItem.item_data for page creation operations."""

    path: str = Field(..., description="Page path (e.g., '/about/')")
    title: str = Field(..., description="Page title")
    page_type: str = Field("content", description="Page type")
    blueprint_name: str | None = Field(None, description="Blueprint to use")
    layout_name: str | None = Field(None, description="Layout to use")
    data: dict[str, Any] = Field(default_factory=dict, description="Page data")
    metadata: dict[str, Any] = Field(default_factory=dict, description="Page metadata")

    @field_validator("page_type")
    @classmethod
    def validate_page_type(cls, v: str) -> str:
        """Validate page_type against field_options.yaml."""
        return FieldOptions.validate("page_types", v)


class PageUpdatePayloadSchema(JSONFieldSchema):
    """OutboxItem.item_data for page update operations."""

    page_id: int = Field(..., description="ID of the page to update")
    path: str | None = Field(None, description="Page path (for reference)")
    changes: dict[str, Any] = Field(..., description="Fields to update")


class PageDeletionPayloadSchema(JSONFieldSchema):
    """OutboxItem.item_data for page deletion operations."""

    page_id: int = Field(..., description="ID of the page to delete")
    path: str | None = Field(None, description="Page path (for reference)")
    reason: str | None = Field(None, description="Reason for deletion")


class BulkOperationPayloadSchema(JSONFieldSchema):
    """OutboxItem.item_data for bulk operations."""

    operation: str = Field(..., description="Bulk operation type")
    item_count: int = Field(..., description="Number of items in bulk operation")
    description: str | None = Field(None, description="Operation description")


# =============================================================================
# COMPONENT PROPS
# =============================================================================


class ComponentPropsBaseSchema(JSONFieldSchema):
    """
    Base schema for Component.props JSONField.

    Components have type-specific props. This is the base with common fields.
    Subclass for specific component types (hero, cta, feature-grid, etc.).
    """

    variant: str | None = Field(None, description="Component variant")
    className: str | None = Field(None, description="Additional CSS classes")


class HeroPropsSchema(ComponentPropsBaseSchema):
    """Props for hero component."""

    headline: str = Field(..., description="Main headline text")
    subheadline: str | None = Field(None, description="Supporting text")
    cta_text: str | None = Field(None, description="Call-to-action button text")
    cta_url: str | None = Field(None, description="Call-to-action URL")
    background_image: str | None = Field(None, description="Background image URL")


class CTAPropsSchema(ComponentPropsBaseSchema):
    """Props for CTA (call-to-action) component."""

    headline: str = Field(..., description="CTA headline")
    description: str | None = Field(None, description="CTA description")
    button_text: str = Field("Get Started", description="Button text")
    button_url: str = Field("#", description="Button URL")


class FeatureGridPropsSchema(ComponentPropsBaseSchema):
    """Props for feature grid component."""

    headline: str | None = Field(None, description="Section headline")
    features: list[dict[str, Any]] = Field(default_factory=list, description="List of features")


# =============================================================================
# BLOCK PROPS
# =============================================================================


class ParagraphBlockPropsSchema(JSONFieldSchema):
    """Props for paragraph block type."""

    content: str = Field(..., description="Paragraph text content (may contain HTML)")


class HeadingBlockPropsSchema(JSONFieldSchema):
    """Props for heading block type."""

    content: str = Field(..., description="Heading text")
    level: int = Field(2, ge=1, le=6, description="Heading level (1-6)")


class ImageBlockPropsSchema(JSONFieldSchema):
    """Props for image block type."""

    src: str = Field(..., description="Image URL")
    alt: str = Field("", description="Alt text for accessibility")
    caption: str | None = Field(None, description="Image caption")
    width: int | None = Field(None, description="Image width")
    height: int | None = Field(None, description="Image height")


class CodeBlockPropsSchema(JSONFieldSchema):
    """Props for code block type."""

    code: str = Field(..., description="Code content")
    language: str = Field("text", description="Programming language for syntax highlighting")
    filename: str | None = Field(None, description="Optional filename to display")


class QuoteBlockPropsSchema(JSONFieldSchema):
    """Props for quote block type."""

    content: str = Field(..., description="Quote text")
    attribution: str | None = Field(None, description="Quote attribution")


# =============================================================================
# AGENT PERMISSIONS
# =============================================================================


class AgentPermissionsSchema(JSONFieldSchema):
    """
    Schema for AgentAPIKey.permissions JSONField.

    Granular permissions for AI agent API keys.
    """

    can_stage: bool = Field(True, description="Can stage content for review")
    can_publish: bool = Field(False, description="Can publish directly without review")
    can_create: bool = Field(True, description="Can create new content")
    can_update: bool = Field(True, description="Can update existing content")
    can_delete: bool = Field(False, description="Can delete/archive content")
    allowed_page_types: list[str] | None = Field(None, description="Restrict to specific page types")
    allowed_blueprints: list[str] | None = Field(None, description="Restrict to specific blueprints")


# =============================================================================
# PAGE VERSION DATA
# =============================================================================


class PageVersionDataSchema(JSONFieldSchema):
    """
    Schema for PageVersion.data JSONField.

    Snapshot of page state at version time.
    """

    title: str = Field(..., description="Page title at this version")
    slug: str = Field(..., description="URL slug at this version")
    path: str = Field(..., description="Full path at this version")
    page_type: str = Field(..., description="Page type at this version")
    blueprint: str | None = Field(None, description="Blueprint name at this version")

    @field_validator("page_type")
    @classmethod
    def validate_page_type(cls, v: str) -> str:
        """Validate page_type against field_options.yaml."""
        return FieldOptions.validate("page_types", v)
