# app/modules/messaging/schemas/email.py
"""
Email template Pydantic schemas for API responses and requests.

Provides schemas for:
- EmailTemplate: Platform email templates
- StoreEmailTemplate: Store-specific template overrides
"""

from datetime import datetime

from pydantic import BaseModel, ConfigDict, Field


class EmailTemplateBase(BaseModel):
    """Base schema for email templates."""

    code: str = Field(..., description="Template code (e.g., 'password_reset')")
    language: str = Field(default="en", description="Language code (en, fr, de, lb)")
    name: str = Field(..., description="Human-readable template name")
    description: str | None = Field(None, description="Template description")
    category: str = Field(..., description="Template category (auth, orders, billing, etc.)")
    subject: str = Field(..., description="Email subject (supports Jinja2 variables)")
    body_html: str = Field(..., description="HTML email body")
    body_text: str | None = Field(None, description="Plain text fallback")
    variables: list[str] = Field(default_factory=list, description="Available variables")


class EmailTemplateCreate(EmailTemplateBase):
    """Schema for creating an email template."""

    required_variables: list[str] = Field(
        default_factory=list, description="Required variables"
    )
    is_platform_only: bool = Field(
        default=False, description="Cannot be overridden by stores"
    )


class EmailTemplateUpdate(BaseModel):
    """Schema for updating an email template."""

    name: str | None = Field(None, description="Human-readable template name")
    description: str | None = Field(None, description="Template description")
    subject: str | None = Field(None, description="Email subject")
    body_html: str | None = Field(None, description="HTML email body")
    body_text: str | None = Field(None, description="Plain text fallback")
    variables: list[str] | None = Field(None, description="Available variables")
    required_variables: list[str] | None = Field(None, description="Required variables")
    is_active: bool | None = Field(None, description="Template active status")


class EmailTemplateResponse(BaseModel):
    """Schema for email template API response."""

    model_config = ConfigDict(from_attributes=True)

    id: int
    code: str
    language: str
    name: str
    description: str | None
    category: str
    subject: str
    body_html: str
    body_text: str | None
    variables: list[str] = Field(default_factory=list)
    required_variables: list[str] = Field(default_factory=list)
    is_active: bool
    is_platform_only: bool
    created_at: datetime
    updated_at: datetime

    @classmethod
    def from_db(cls, template) -> "EmailTemplateResponse":
        """Create response from database model."""
        return cls(
            id=template.id,
            code=template.code,
            language=template.language,
            name=template.name,
            description=template.description,
            category=template.category,
            subject=template.subject,
            body_html=template.body_html,
            body_text=template.body_text,
            variables=template.variables_list,
            required_variables=template.required_variables_list,
            is_active=template.is_active,
            is_platform_only=template.is_platform_only,
            created_at=template.created_at,
            updated_at=template.updated_at,
        )


class EmailTemplateSummary(BaseModel):
    """Summary schema for template list views."""

    model_config = ConfigDict(from_attributes=True)

    id: int
    code: str
    name: str
    category: str
    languages: list[str] = Field(default_factory=list)
    is_platform_only: bool
    is_active: bool

    @classmethod
    def from_db_list(cls, templates: list) -> list["EmailTemplateSummary"]:
        """
        Create summaries from database models, grouping by code.

        Args:
            templates: List of EmailTemplate models

        Returns:
            List of EmailTemplateSummary grouped by template code
        """
        # Group templates by code
        by_code: dict[str, list] = {}
        for t in templates:
            if t.code not in by_code:
                by_code[t.code] = []
            by_code[t.code].append(t)

        summaries = []
        for code, group in by_code.items():
            first = group[0]
            summaries.append(
                cls(
                    id=first.id,
                    code=code,
                    name=first.name,
                    category=first.category,
                    languages=[t.language for t in group],
                    is_platform_only=first.is_platform_only,
                    is_active=first.is_active,
                )
            )

        return summaries


# Store Email Template Schemas


class StoreEmailTemplateCreate(BaseModel):
    """Schema for creating a store email template override."""

    template_code: str = Field(..., description="Template code to override")
    language: str = Field(default="en", description="Language code")
    name: str | None = Field(None, description="Custom name (uses platform default if None)")
    subject: str = Field(..., description="Custom email subject")
    body_html: str = Field(..., description="Custom HTML body")
    body_text: str | None = Field(None, description="Custom plain text body")


class StoreEmailTemplateUpdate(BaseModel):
    """Schema for updating a store email template override."""

    name: str | None = Field(None, description="Custom name")
    subject: str | None = Field(None, description="Custom email subject")
    body_html: str | None = Field(None, description="Custom HTML body")
    body_text: str | None = Field(None, description="Custom plain text body")
    is_active: bool | None = Field(None, description="Override active status")


class StoreEmailTemplateResponse(BaseModel):
    """Schema for store email template override API response."""

    model_config = ConfigDict(from_attributes=True)

    id: int
    store_id: int
    template_code: str
    language: str
    name: str | None
    subject: str
    body_html: str
    body_text: str | None
    is_active: bool
    created_at: datetime
    updated_at: datetime


class EmailTemplateWithOverrideStatus(BaseModel):
    """
    Schema showing template with store override status.

    Used in store UI to show which templates have been customized.
    """

    model_config = ConfigDict(from_attributes=True)

    code: str
    name: str
    category: str
    languages: list[str]
    is_platform_only: bool
    has_override: bool = Field(
        default=False, description="Whether store has customized this template"
    )
    override_languages: list[str] = Field(
        default_factory=list,
        description="Languages with store overrides",
    )


# Email Preview/Test Schemas


class EmailPreviewRequest(BaseModel):
    """Schema for requesting an email preview."""

    template_code: str = Field(..., description="Template code")
    language: str = Field(default="en", description="Language code")
    variables: dict[str, str] = Field(
        default_factory=dict, description="Variables to inject"
    )


class EmailPreviewResponse(BaseModel):
    """Schema for email preview response."""

    subject: str
    body_html: str
    body_text: str | None


class EmailTestRequest(BaseModel):
    """Schema for sending a test email."""

    template_code: str = Field(..., description="Template code")
    language: str = Field(default="en", description="Language code")
    to_email: str = Field(..., description="Recipient email address")
    variables: dict[str, str] = Field(
        default_factory=dict, description="Variables to inject"
    )


class EmailTestResponse(BaseModel):
    """Schema for test email response."""

    success: bool
    message: str
    email_log_id: int | None = None


# =============================================================================
# Email Log (Audit) Schemas
# =============================================================================


class EmailLogListItem(BaseModel):
    """Compact email log item (no body content)."""

    id: int
    recipient_email: str
    recipient_name: str | None = None
    subject: str
    status: str
    template_code: str | None = None
    provider: str | None = None
    store_id: int | None = None
    related_type: str | None = None
    related_id: int | None = None
    created_at: str | None = None
    sent_at: str | None = None
    error_message: str | None = None


class EmailLogDetail(BaseModel):
    """Full email log detail including body content."""

    id: int
    recipient_email: str
    recipient_name: str | None = None
    subject: str
    status: str
    template_code: str | None = None
    provider: str | None = None
    store_id: int | None = None
    user_id: int | None = None
    related_type: str | None = None
    related_id: int | None = None
    from_email: str | None = None
    from_name: str | None = None
    reply_to: str | None = None
    body_html: str | None = None
    body_text: str | None = None
    error_message: str | None = None
    retry_count: int = 0
    provider_message_id: str | None = None
    created_at: str | None = None
    sent_at: str | None = None
    delivered_at: str | None = None
    opened_at: str | None = None
    clicked_at: str | None = None
    extra_data: str | None = None


class EmailLogListResponse(BaseModel):
    """Paginated email log list."""

    items: list[EmailLogListItem]
    total: int
    page: int
    per_page: int
    total_pages: int


class EmailLogStatsResponse(BaseModel):
    """Email log statistics."""

    by_status: dict[str, int] = Field(default_factory=dict)
    by_template: dict[str, int] = Field(default_factory=dict)
    total: int = 0
