"""
SiteTemplate ORM model — platform-level, merchant-agnostic template store.

PRD-010 Templates Management.

Design:
  - All 28 templates are platform-level records (no merchant_id).
  - Templates cover three types: auth (platform branding), payment (merchant
    branding injection via {{ primary_color }} / {{ accent_color }} / {{ logo_url }}
    variables), and user_invite (merchant branding injection).
  - SMS templates carry body_text only; PDF templates carry body_html only;
    email templates carry both body_html and body_text.
  - The `variables` JSON column documents the Jinja2-style variable names that
    each template expects at render time.
  - Soft-delete pattern (deleted_at) consistent with all other content tables.
"""

from __future__ import annotations

from datetime import datetime
from enum import Enum
from typing import List, Optional

from sqlalchemy import Boolean, Index, Integer, String, Text, DateTime, JSON, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.sql import func

from src.apps.base.models.base import Base


class TemplateChannel(str, Enum):
    """Delivery channel for the template."""
    EMAIL = "email"
    SMS = "sms"
    PDF = "pdf"


class TemplateType(str, Enum):
    """Functional category for the template."""
    AUTH = "auth"
    PAYMENT = "payment"
    USER_INVITE = "user_invite"


class SiteTemplate(Base):
    """
    SiteTemplate Model: ORM class for the site_templates table.

    Platform-wide template store that replaces the legacy notification_templates
    table.  Templates are rendered at runtime by the notification service with
    Jinja2; the `variables` list documents the expected context keys.
    """

    __tablename__ = "site_templates"

    __table_args__ = (
        UniqueConstraint("template_key", name="uq_site_templates_template_key"),
        Index("ix_site_templates_channel", "channel"),
        Index("ix_site_templates_template_type", "template_type"),
    )

    # ---------------------------------------------------------------------------
    # Primary key
    # ---------------------------------------------------------------------------
    id: Mapped[int] = mapped_column(
        Integer, primary_key=True, index=True, autoincrement=True
    )

    # ---------------------------------------------------------------------------
    # Identity
    # ---------------------------------------------------------------------------
    template_key: Mapped[str] = mapped_column(
        String(100),
        nullable=False,
        unique=True,
        comment="Machine-readable key used to look up the template at render time",
    )
    template_name: Mapped[str] = mapped_column(
        String(255),
        nullable=False,
        comment="Human-readable display name shown in the admin UI",
    )
    description: Mapped[Optional[str]] = mapped_column(
        Text,
        nullable=True,
        comment="Optional admin-facing description of when this template is sent",
    )

    # ---------------------------------------------------------------------------
    # Classification
    # ---------------------------------------------------------------------------
    channel: Mapped[str] = mapped_column(
        String(10),
        nullable=False,
        comment="Delivery channel: email | sms | pdf",
    )
    template_type: Mapped[str] = mapped_column(
        String(20),
        nullable=False,
        comment="Functional category: auth | payment | user_invite",
    )

    # ---------------------------------------------------------------------------
    # Content
    # ---------------------------------------------------------------------------
    subject: Mapped[Optional[str]] = mapped_column(
        String(255),
        nullable=True,
        comment="Email subject line; null for SMS and PDF templates",
    )
    body_html: Mapped[Optional[str]] = mapped_column(
        Text,
        nullable=True,
        comment="Full HTML body; null for SMS-only templates",
    )
    body_text: Mapped[Optional[str]] = mapped_column(
        Text,
        nullable=True,
        comment="Plain-text body; used as SMS message and email plain-text fallback",
    )

    # ---------------------------------------------------------------------------
    # Branding defaults (overridden at render time by merchant settings)
    # ---------------------------------------------------------------------------
    primary_color: Mapped[str] = mapped_column(
        String(7),
        nullable=False,
        default="#28B4ED",
        server_default="#28B4ED",
        comment="Hex color injected as {{ primary_color }} in payment/invite templates",
    )
    accent_color: Mapped[str] = mapped_column(
        String(7),
        nullable=False,
        default="#FB7585",
        server_default="#FB7585",
        comment="Hex color injected as {{ accent_color }} in payment/invite templates",
    )
    text_color: Mapped[str] = mapped_column(
        String(7),
        nullable=False,
        default="#252525",
        server_default="#252525",
        comment="Hex color injected as {{ text_color }} in payment/invite templates",
    )

    # ---------------------------------------------------------------------------
    # Variable manifest
    # ---------------------------------------------------------------------------
    variables: Mapped[List] = mapped_column(
        JSON,
        nullable=False,
        default=list,
        server_default="[]",
        comment="Ordered list of Jinja2 variable names expected by this template",
    )

    # ---------------------------------------------------------------------------
    # Status
    # ---------------------------------------------------------------------------
    is_active: Mapped[bool] = mapped_column(
        Boolean,
        nullable=False,
        default=True,
        server_default="true",
        comment="Inactive templates are skipped by the notification dispatcher",
    )

    # ---------------------------------------------------------------------------
    # Timestamps
    # ---------------------------------------------------------------------------
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        nullable=False,
        server_default=func.now(),
        comment="Row creation timestamp (UTC)",
    )
    updated_at: Mapped[Optional[datetime]] = mapped_column(
        DateTime(timezone=True),
        nullable=True,
        onupdate=func.now(),
        comment="Last modification timestamp; null until first update",
    )
    deleted_at: Mapped[Optional[datetime]] = mapped_column(
        DateTime(timezone=True),
        nullable=True,
        comment="Soft-delete timestamp; non-null rows are excluded from all queries",
    )
