"""
Pydantic schemas for Email model JSONFields.

These schemas validate the JSONFields on email-related models:
- IncomingEmail: cc, bcc, raw_headers, references, attachments,
  secondary_categories, priority_reasons, extracted_entities,
  suggested_actions, labels, gmail_labels
- IncomingEmailAction: metadata
- GmailCredentials: scopes
- EmailEvent: raw_payload
- Subscriber: preferences
- Campaign: segment_filter

Usage:
    from lightwave.schema.pydantic.models.emails import (
        EmailAttachmentSchema,
        ExtractedEntitiesSchema,
        ActionMetadataSchema,
        SubscriberPreferencesSchema,
        SegmentFilterSchema,
    )
"""

from typing import Any

from pydantic import Field

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


class EmailRecipientSchema(JSONFieldSchema):
    """
    Schema for email recipient in cc/bcc lists.

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

    email: str = Field(..., description="Email address")
    name: str = Field("", description="Display name")


class RawEmailHeadersSchema(JSONFieldSchema):
    """
    Schema for IncomingEmail.raw_headers JSONField.

    Parsed email headers from the original message.

    Example:
        {
            "Message-ID": "<abc123@mail.example.com>",
            "Date": "Mon, 15 Jan 2024 10:30:00 -0800",
            "From": "sender@example.com",
            "To": "recipient@company.com",
            "Subject": "Meeting Tomorrow",
            "Content-Type": "multipart/mixed",
            "X-Priority": "1"
        }
    """

    # Standard headers stored as-is
    # This schema allows extra fields for flexibility


class EmailAttachmentSchema(JSONFieldSchema):
    """
    Schema for individual attachment in IncomingEmail.attachments list.

    Metadata for attachments stored in S3.

    Example:
        {
            "name": "invoice.pdf",
            "size": 102400,
            "content_type": "application/pdf",
            "s3_key": "attachments/2024/01/abc123.pdf"
        }
    """

    name: str = Field(..., description="Original filename")
    size: int = Field(..., ge=0, description="File size in bytes")
    content_type: str = Field(..., description="MIME type")
    s3_key: str = Field("", description="S3 key for stored attachment")
    content_id: str | None = Field(None, description="Content-ID for inline attachments")


class ExtractedEntitiesSchema(JSONFieldSchema):
    """
    Schema for IncomingEmail.extracted_entities JSONField.

    AI-extracted entities from email content.

    Example:
        {
            "amounts": ["$1,200", "$50.00"],
            "dates": ["January 15", "next Monday"],
            "people": ["John Smith", "Jane Doe"],
            "companies": ["Acme Corp"],
            "phone_numbers": ["555-123-4567"],
            "urls": ["https://example.com/invoice/123"]
        }
    """

    amounts: list[str] = Field(default_factory=list, description="Dollar amounts found")
    dates: list[str] = Field(default_factory=list, description="Date references found")
    people: list[str] = Field(default_factory=list, description="Person names found")
    companies: list[str] = Field(default_factory=list, description="Company names found")
    phone_numbers: list[str] = Field(default_factory=list, description="Phone numbers found")
    urls: list[str] = Field(default_factory=list, description="URLs found")
    addresses: list[str] = Field(default_factory=list, description="Physical addresses found")


class SuggestedActionSchema(JSONFieldSchema):
    """
    Schema for individual action in IncomingEmail.suggested_actions list.

    AI-suggested action with context.

    Example:
        {
            "action": "create_task",
            "confidence": 0.85,
            "reason": "Invoice due date mentioned",
            "params": {"due_date": "2024-01-22", "title": "Pay invoice #123"}
        }
    """

    action: str = Field(..., description="Action type (create_task, reply, archive, forward, etc.)")
    confidence: float = Field(0.5, ge=0.0, le=1.0, description="Confidence score")
    reason: str = Field("", description="Reason for suggestion")
    params: dict[str, Any] = Field(default_factory=dict, description="Action parameters")


class ActionMetadataSchema(JSONFieldSchema):
    """
    Schema for IncomingEmailAction.metadata JSONField.

    Action-specific data for audit trail.

    Example:
        {
            "old_category": "uncategorized",
            "new_category": "financial",
            "task_id": "abc123",
            "label_added": "urgent"
        }
    """

    old_category: str | None = Field(None, description="Previous category")
    new_category: str | None = Field(None, description="New category")
    old_priority: str | None = Field(None, description="Previous priority")
    new_priority: str | None = Field(None, description="New priority")
    task_id: str | None = Field(None, description="Created task ID")
    label_added: str | None = Field(None, description="Label that was added")
    label_removed: str | None = Field(None, description="Label that was removed")
    note_text: str | None = Field(None, description="Note content if note was added")
    gmail_label_id: str | None = Field(None, description="Gmail label ID for sync actions")


class GmailScopesSchema(JSONFieldSchema):
    """
    Schema for GmailCredentials.scopes JSONField.

    OAuth scopes granted by the user for Gmail API access.

    Example:
        [
            "https://www.googleapis.com/auth/gmail.readonly",
            "https://www.googleapis.com/auth/gmail.modify"
        ]
    """

    scopes: list[str] = Field(default_factory=list, description="OAuth scope URLs")

    @classmethod
    def from_list(cls, scopes: list[str]) -> "GmailScopesSchema":
        return cls(scopes=scopes)

    def to_list(self) -> list[str]:
        return self.scopes


class EmailEventPayloadSchema(JSONFieldSchema):
    """
    Schema for EmailEvent.raw_payload JSONField.

    Raw SES webhook event payload.

    Example:
        {
            "eventType": "Delivery",
            "mail": {"messageId": "abc123", "timestamp": "..."},
            "delivery": {"timestamp": "...", "recipients": ["..."]}
        }
    """

    eventType: str | None = Field(None, description="SES event type")
    mail: dict[str, Any] = Field(default_factory=dict, description="Mail metadata")
    delivery: dict[str, Any] | None = Field(None, description="Delivery details")
    bounce: dict[str, Any] | None = Field(None, description="Bounce details")
    complaint: dict[str, Any] | None = Field(None, description="Complaint details")
    open: dict[str, Any] | None = Field(None, alias="open", description="Open tracking")
    click: dict[str, Any] | None = Field(None, description="Click tracking")


class SubscriberPreferencesSchema(JSONFieldSchema):
    """
    Schema for Subscriber.preferences JSONField.

    Subscriber communication preferences.

    Example:
        {
            "frequency": "weekly",
            "topics": ["product_updates", "tutorials"],
            "format": "html",
            "timezone": "America/Los_Angeles"
        }
    """

    frequency: str = Field("weekly", description="Email frequency (daily, weekly, monthly)")
    topics: list[str] = Field(default_factory=list, description="Subscribed topic categories")
    format: str = Field("html", description="Preferred format (html, text)")
    timezone: str | None = Field(None, description="Preferred timezone")
    unsubscribed_topics: list[str] = Field(default_factory=list, description="Topics user unsubscribed from")


class SegmentFilterSchema(JSONFieldSchema):
    """
    Schema for Campaign.segment_filter JSONField.

    Filter criteria for campaign audience segmentation.

    Example:
        {
            "status": "active",
            "source": ["website", "api"],
            "subscribed_after": "2024-01-01",
            "topics_include": ["product_updates"],
            "topics_exclude": ["promotions"]
        }
    """

    status: str | None = Field(None, description="Subscriber status filter")
    source: list[str] | None = Field(None, description="Source filter (website, api, import)")
    subscribed_after: str | None = Field(None, description="Subscribed after date (YYYY-MM-DD)")
    subscribed_before: str | None = Field(None, description="Subscribed before date")
    topics_include: list[str] = Field(default_factory=list, description="Must be subscribed to these topics")
    topics_exclude: list[str] = Field(default_factory=list, description="Must not be subscribed to these topics")
    custom_filters: dict[str, Any] = Field(default_factory=dict, description="Additional custom filter criteria")


# =============================================================================
# AUTO-REPLY / EMAIL DRAFT SCHEMAS
# =============================================================================


class AutoReplyConditionSchema(JSONFieldSchema):
    """
    Schema for a single auto-reply trigger condition.

    Example:
        {
            "field": "category",
            "operator": "equals",
            "value": "customer"
        }
    """

    field: str = Field(..., description="Field to match (category, priority, sender, subject, body)")
    operator: str = Field(
        "contains",
        description="Match operator (equals, contains, starts_with, ends_with, regex, in_list, from_domain)",
    )
    value: str | list[str] = Field(..., description="Value(s) to match against")
    case_sensitive: bool = Field(False, description="Whether match is case-sensitive")


class AutoReplyRuleSchema(JSONFieldSchema):
    """
    Schema for AutoReplyRule configuration.

    Defines when and how to generate auto-reply drafts.

    Example:
        {
            "name": "Customer Follow-up",
            "trigger_type": "on_category",
            "conditions": [
                {"field": "category", "operator": "equals", "value": "customer"}
            ],
            "generation_mode": "ai_generated",
            "template_id": null,
            "prompt_context": "Professional follow-up acknowledging their inquiry",
            "delay_minutes": 0,
            "enabled": true
        }
    """

    name: str = Field(..., description="Rule name for identification")
    trigger_type: str = Field(
        "on_category",
        description="Trigger type (on_received, on_category, on_priority, on_sender, on_keyword, on_no_response)",
    )
    conditions: list[AutoReplyConditionSchema] = Field(
        default_factory=list, description="Conditions that must all match"
    )
    conditions_match: str = Field("all", description="How to combine conditions: 'all' (AND) or 'any' (OR)")
    generation_mode: str = Field(
        "ai_generated",
        description="How to generate reply (template, ai_generated, ai_with_template)",
    )
    template_id: str | None = Field(None, description="Template ID if using template mode")
    prompt_context: str = Field("", description="Additional context for AI generation")
    tone: str = Field("professional", description="Tone for AI generation (professional, friendly, formal)")
    delay_minutes: int = Field(0, ge=0, description="Minutes to wait before generating draft")
    enabled: bool = Field(True, description="Whether rule is active")
    priority: int = Field(0, description="Rule priority (higher = evaluated first)")


class EmailDraftSchema(JSONFieldSchema):
    """
    Schema for EmailDraft/OutboxItem email draft data.

    Used in OutboxItem.item_data when item_type='email_draft'.

    Example:
        {
            "incoming_email_id": "uuid",
            "rule_id": "uuid",
            "to": "sender@example.com",
            "cc": [],
            "subject": "Re: Original Subject",
            "body_text": "Draft reply text",
            "body_html": "<p>Draft reply text</p>",
            "in_reply_to": "<message-id@example.com>",
            "references": ["<msg1@ex.com>", "<msg2@ex.com>"],
            "send_at": "2026-01-25T09:00:00Z",
            "generation_metadata": {...}
        }
    """

    incoming_email_id: str = Field(..., description="UUID of the IncomingEmail this replies to")
    rule_id: str | None = Field(None, description="UUID of AutoReplyRule that triggered this draft")
    to: str = Field(..., description="Recipient email address")
    cc: list[str] = Field(default_factory=list, description="CC recipients")
    bcc: list[str] = Field(default_factory=list, description="BCC recipients")
    subject: str = Field(..., description="Email subject line")
    body_text: str = Field(..., description="Plain text email body")
    body_html: str = Field("", description="HTML email body")
    in_reply_to: str | None = Field(None, description="Message-ID of email being replied to")
    references: list[str] = Field(default_factory=list, description="Message-ID chain for threading")
    send_at: str | None = Field(None, description="Scheduled send time (ISO 8601)")
    from_address: str | None = Field(None, description="From address override (defaults to tenant noreply)")
    generation_metadata: dict[str, Any] = Field(
        default_factory=dict,
        description="Metadata about how draft was generated (model, tokens, rule, etc.)",
    )


class EmailDraftGenerationMetadataSchema(JSONFieldSchema):
    """
    Schema for generation metadata within EmailDraftSchema.

    Tracks how the draft was created for audit/debugging.

    Example:
        {
            "model": "claude-3-haiku",
            "tokens_used": 450,
            "generation_time_ms": 1200,
            "rule_name": "Customer Follow-up",
            "original_subject": "Question about pricing",
            "original_sender": "customer@example.com"
        }
    """

    model: str | None = Field(None, description="AI model used for generation")
    tokens_used: int | None = Field(None, ge=0, description="Tokens consumed")
    generation_time_ms: int | None = Field(None, ge=0, description="Generation time in ms")
    rule_name: str | None = Field(None, description="Name of rule that triggered")
    original_subject: str = Field("", description="Subject of original email")
    original_sender: str = Field("", description="Sender of original email")
    original_snippet: str = Field("", description="First ~200 chars of original email")
    prompt_used: str = Field("", description="Prompt sent to AI (for debugging)")
