"""
Email API schemas.

These schemas provide type-safe request/response structures for
email template management and email sending operations.

Templates are defined in definitions/email.yaml (SST) and can be
rendered with dynamic variables.

Usage:
    from lightwave.schema.pydantic.contracts.api.emails import (
        EmailTemplateSchema,
        EmailRenderRequest,
        EmailRenderResponse,
        EmailSendRequest,
    )

    @router.get("/email/templates/", response=EmailTemplateListResponse)
    def list_templates(request):
        ...

    @router.post("/email/render/", response=EmailRenderResponse)
    def render_email(request, payload: EmailRenderRequest):
        ...
"""

from datetime import datetime
from typing import Any, Literal

from pydantic import EmailStr, Field

from lightwave.schema.pydantic.core.base import (
    APIRequestSchema,
    APIResponseSchema,
    LightwaveBaseSchema,
)

# =============================================================================
# Email Template Schemas
# =============================================================================


class EmailTemplateSchema(LightwaveBaseSchema):
    """
    Email template definition.

    Represents a template from email.yaml with its subject,
    variables, and routing configuration.

    Example:
        {
            "name": "password_reset",
            "subject_template": "Reset your {tenant_name} password",
            "from_type": "transactional",
            "variables": ["user.name", "user.email", "reset_url", "expiry_hours"]
        }
    """

    name: str = Field(..., description="Template identifier")
    subject_template: str = Field(..., description="Subject line with {variables}")
    from_type: Literal["transactional", "notifications", "marketing", "support", "billing"] = Field(
        ..., description="Routing type from email.yaml"
    )
    variables: list[str] = Field(default_factory=list, description="Required template variables")
    body_text: str | None = Field(None, description="Plain text body template")
    body_html: str | None = Field(None, description="HTML body template")
    is_active: bool = Field(True, description="Whether template is available")


class EmailTemplateListResponse(APIResponseSchema):
    """
    List of available email templates.

    Example response:
        {
            "templates": [...],
            "total": 15
        }
    """

    id: int | None = None  # Override
    created_at: datetime | None = None  # Override
    updated_at: datetime | None = None  # Override

    templates: list[EmailTemplateSchema] = Field(default_factory=list, description="Available templates")
    total: int = Field(0, ge=0, description="Total template count")


# =============================================================================
# Email Render Schemas
# =============================================================================


class EmailRenderRequest(APIRequestSchema):
    """
    Request to render an email template.

    Example:
        POST /api/email/render/
        {
            "template": "password_reset",
            "variables": {
                "user.name": "John Doe",
                "reset_url": "https://...",
                "expiry_hours": 24
            },
            "tenant": "cineos"
        }
    """

    template: str = Field(..., description="Template name from email.yaml")
    variables: dict[str, Any] = Field(default_factory=dict, description="Template variable values")
    tenant: str | None = Field(None, description="Tenant for domain resolution")
    format: Literal["html", "text", "both"] = Field("both", description="Output format")


class EmailRenderResponse(APIResponseSchema):
    """
    Rendered email content.

    Example response:
        {
            "subject": "Reset your cineOS password",
            "html": "<html>...",
            "plain_text": "Hi John Doe, ...",
            "from_address": "noreply@cineos.io"
        }
    """

    id: int | None = None  # Override
    created_at: datetime | None = None  # Override
    updated_at: datetime | None = None  # Override

    subject: str = Field(..., description="Rendered subject line")
    html: str | None = Field(None, description="Rendered HTML body")
    plain_text: str | None = Field(None, description="Rendered plain text body")
    from_address: str = Field(..., description="Resolved from address")
    reply_to: str | None = Field(None, description="Reply-to address if different")


# =============================================================================
# Email Send Schemas
# =============================================================================


class EmailRecipient(LightwaveBaseSchema):
    """
    Email recipient with optional name.

    Example:
        {"email": "john@example.com", "name": "John Doe"}
    """

    email: EmailStr = Field(..., description="Recipient email address")
    name: str | None = Field(None, description="Recipient display name")


class EmailSendRequest(APIRequestSchema):
    """
    Request to send an email.

    Can either use a template (preferred) or provide raw content.

    Example (template):
        POST /api/email/send/
        {
            "template": "team_invite",
            "to": [{"email": "new@example.com", "name": "New User"}],
            "variables": {
                "inviter.name": "John",
                "team.name": "Acme"
            }
        }

    Example (raw):
        POST /api/email/send/
        {
            "to": [{"email": "user@example.com"}],
            "subject": "Custom subject",
            "body_html": "<p>Hello</p>",
            "body_text": "Hello"
        }
    """

    # Recipients
    to: list[EmailRecipient] = Field(..., min_length=1, description="Primary recipients")
    cc: list[EmailRecipient] = Field(default_factory=list, description="CC recipients")
    bcc: list[EmailRecipient] = Field(default_factory=list, description="BCC recipients")

    # Template-based (preferred)
    template: str | None = Field(None, description="Template name from email.yaml")
    variables: dict[str, Any] = Field(default_factory=dict, description="Template variables")

    # Raw content (fallback)
    subject: str | None = Field(None, description="Subject (required if no template)")
    body_html: str | None = Field(None, description="HTML body")
    body_text: str | None = Field(None, description="Plain text body")

    # Options
    from_address: str | None = Field(None, description="Override from address")
    reply_to: str | None = Field(None, description="Reply-to address")
    tags: list[str] = Field(default_factory=list, description="Tracking tags")
    metadata: dict[str, str] = Field(default_factory=dict, description="Custom metadata for webhooks")
    send_at: datetime | None = Field(None, description="Schedule send time")


class EmailSendResponse(APIResponseSchema):
    """
    Response after sending an email.

    Example response:
        {
            "message_id": "01234567-89ab-cdef-0123-456789abcdef",
            "status": "queued",
            "queued_at": "2024-01-20T10:30:00Z",
            "recipient_count": 3
        }
    """

    id: int | None = None  # Override
    created_at: datetime | None = None  # Override
    updated_at: datetime | None = None  # Override

    message_id: str = Field(..., description="Unique message identifier")
    status: Literal["queued", "sent", "failed"] = Field(..., description="Send status")
    queued_at: datetime = Field(..., description="When message was queued")
    sent_at: datetime | None = Field(None, description="When message was sent")
    recipient_count: int = Field(..., ge=1, description="Number of recipients")
    error: str | None = Field(None, description="Error message if failed")


# =============================================================================
# Email Log Schemas (Read-only)
# =============================================================================


class EmailLogSchema(APIResponseSchema):
    """
    Email log entry for audit trail.

    Read-only schema for viewing sent email history.
    """

    message_id: str = Field(..., description="Unique message identifier")
    template: str | None = Field(None, description="Template used")
    from_address: str = Field(..., description="From address")
    to_addresses: list[str] = Field(..., description="Recipient addresses")
    subject: str = Field(..., description="Email subject")
    status: Literal["queued", "sent", "delivered", "bounced", "complained", "failed"] = Field(
        ..., description="Current status"
    )
    sent_at: datetime | None = Field(None, description="When sent")
    delivered_at: datetime | None = Field(None, description="When delivered")
    opened_at: datetime | None = Field(None, description="When first opened")
    clicked_at: datetime | None = Field(None, description="When first clicked")
    bounce_type: str | None = Field(None, description="Bounce type if bounced")
    bounce_reason: str | None = Field(None, description="Bounce reason")
    tags: list[str] = Field(default_factory=list, description="Tracking tags")
