"""Commune SDK types — mirrors the Node.js SDK type definitions exactly."""

from typing import Any, Dict, List, Literal, Optional, Union
from pydantic import BaseModel, Field


# ── Enums / Literals ─────────────────────────────────────────────────────────

Channel = Literal["email"]
Direction = Literal["inbound", "outbound"]
ParticipantRole = Literal["sender", "to", "cc", "bcc", "mentioned", "participant"]


# ── Core Models ──────────────────────────────────────────────────────────────


class Participant(BaseModel):
    """A participant in an email message."""

    role: ParticipantRole
    identity: str


class MessageMetadata(BaseModel):
    """Metadata attached to every message."""

    created_at: str
    subject: Optional[str] = None
    in_reply_to: Optional[str] = None
    references: Optional[List[str]] = None
    is_private: Optional[bool] = None
    domain_id: Optional[str] = None
    inbox_id: Optional[str] = None
    inbox_address: Optional[str] = None
    message_id: Optional[str] = None
    provider: Optional[str] = None
    extracted_data: Optional[Dict[str, Any]] = None


class Message(BaseModel):
    """A single email message."""

    id: Optional[str] = Field(None, alias="_id")
    channel: Channel = "email"
    message_id: str
    conversation_id: str
    direction: Direction
    participants: List[Participant] = []
    content: str = ""
    content_html: Optional[str] = None
    attachments: List[str] = []
    created_at: str = ""
    metadata: MessageMetadata

    class Config:
        populate_by_name = True


# ── Threads ──────────────────────────────────────────────────────────────────


class Thread(BaseModel):
    """A thread (conversation) summary."""

    thread_id: str
    subject: Optional[str] = None
    last_message_at: str
    first_message_at: Optional[str] = None
    message_count: int = 0
    snippet: Optional[str] = None
    last_direction: Optional[Direction] = None
    inbox_id: Optional[str] = None
    domain_id: Optional[str] = None
    has_attachments: bool = False


class ThreadList(BaseModel):
    """Paginated list of threads."""

    data: List[Thread] = []
    next_cursor: Optional[str] = None
    has_more: bool = False


# ── Domains ──────────────────────────────────────────────────────────────────


class InboxWebhook(BaseModel):
    """Webhook configuration for an inbox."""

    endpoint: Optional[str] = None
    events: Optional[List[str]] = None
    secret: Optional[str] = None


class Inbox(BaseModel):
    """An inbox within a domain."""

    id: str
    local_part: str = Field("", alias="localPart")
    address: Optional[str] = None
    agent: Optional[Dict[str, Any]] = None
    webhook: Optional[Union[InboxWebhook, str]] = None
    extraction_schema: Optional[Dict[str, Any]] = Field(None, alias="extractionSchema")
    created_at: Optional[str] = Field(None, alias="createdAt")
    status: Optional[str] = None
    domain_id: Optional[str] = None
    domain_name: Optional[str] = None

    class Config:
        populate_by_name = True


class DomainWebhook(BaseModel):
    """Webhook configuration for a domain."""

    id: Optional[str] = None
    endpoint: Optional[str] = None
    events: Optional[List[str]] = None
    secret: Optional[str] = None


class Domain(BaseModel):
    """A domain entry."""

    id: str
    name: Optional[str] = None
    status: Optional[str] = None
    region: Optional[str] = None
    records: Optional[List[Any]] = None
    created_at: Optional[str] = Field(None, alias="createdAt")
    inboxes: Optional[List[Inbox]] = None

    class Config:
        populate_by_name = True


# ── Attachments ──────────────────────────────────────────────────────────────


class Attachment(BaseModel):
    """Attachment metadata."""

    attachment_id: str
    message_id: Optional[str] = None
    filename: str
    mime_type: str
    size: int
    source: Optional[str] = None
    storage_type: Optional[str] = None


class AttachmentUpload(BaseModel):
    """Response from uploading an attachment."""

    attachment_id: str
    filename: str
    mime_type: str
    size: int


class AttachmentUrl(BaseModel):
    """A temporary URL to download an attachment."""

    url: str
    expires_in: int = Field(0, alias="expiresIn")
    filename: str
    mime_type: str = Field("", alias="mimeType")
    size: int = 0

    class Config:
        populate_by_name = True


# ── Payloads ─────────────────────────────────────────────────────────────────


class SendMessagePayload(BaseModel):
    """Payload for sending an email."""

    to: Union[str, List[str]]
    subject: str = ""
    html: Optional[str] = None
    text: Optional[str] = None
    cc: Optional[List[str]] = None
    bcc: Optional[List[str]] = None
    reply_to: Optional[Union[str, List[str]]] = None
    thread_id: Optional[str] = None
    domain_id: Optional[str] = Field(None, alias="domainId")
    inbox_id: Optional[str] = Field(None, alias="inboxId")
    attachments: Optional[List[str]] = None
    headers: Optional[Dict[str, str]] = None
    from_address: Optional[str] = Field(None, alias="from")

    class Config:
        populate_by_name = True


class CreateDomainPayload(BaseModel):
    """Payload for creating a domain."""

    name: str
    region: Optional[str] = None
