# app/modules/messaging/models/store_email_settings.py
"""
Store Email Settings model for store-specific email configuration.

This model stores store SMTP/email provider settings, enabling stores to:
- Send emails from their own domain/email address
- Use their own SMTP server or email provider (tier-gated)
- Customize sender name, reply-to address, and signature

Architecture:
- Stores MUST configure email settings to send transactional emails
- Platform emails (billing, subscription) still use platform settings
- Advanced providers (SendGrid, Mailgun, SES) are tier-gated (Business+)
- "Powered by Orion" footer is added for Essential/Professional tiers
"""

import enum
from datetime import UTC, datetime

from sqlalchemy import (
    Boolean,
    Column,
    DateTime,
    ForeignKey,
    Index,
    Integer,
    String,
    Text,
)
from sqlalchemy.orm import relationship

from app.core.database import Base
from models.database.base import TimestampMixin


class EmailProvider(str, enum.Enum):
    """Supported email providers."""

    SMTP = "smtp"  # Standard SMTP (all tiers)
    SENDGRID = "sendgrid"  # SendGrid API (Business+ tier)
    MAILGUN = "mailgun"  # Mailgun API (Business+ tier)
    SES = "ses"  # Amazon SES (Business+ tier)


# Providers that require Business+ tier
PREMIUM_EMAIL_PROVIDERS = {
    EmailProvider.SENDGRID,
    EmailProvider.MAILGUN,
    EmailProvider.SES,
}


class StoreEmailSettings(Base, TimestampMixin):
    """
    Store email configuration for sending transactional emails.

    This is a one-to-one relationship with Store.
    Stores must configure this to send emails to their customers.
    """

    __tablename__ = "store_email_settings"

    id = Column(Integer, primary_key=True, index=True)
    store_id = Column(
        Integer,
        ForeignKey("stores.id", ondelete="CASCADE"),
        unique=True,
        nullable=False,
        index=True,
    )

    # =========================================================================
    # Sender Identity (Required)
    # =========================================================================
    from_email = Column(String(255), nullable=False)  # e.g., orders@storeshop.lu
    from_name = Column(String(100), nullable=False)  # e.g., "StoreShop"
    reply_to_email = Column(String(255), nullable=True)  # Optional reply-to address

    # =========================================================================
    # Email Signature/Footer (Optional)
    # =========================================================================
    signature_text = Column(Text, nullable=True)  # Plain text signature
    signature_html = Column(Text, nullable=True)  # HTML signature (footer)

    # =========================================================================
    # Provider Configuration
    # =========================================================================
    provider = Column(
        String(20),
        default=EmailProvider.SMTP.value,
        nullable=False,
    )

    # =========================================================================
    # SMTP Settings (used when provider=smtp)
    # =========================================================================
    smtp_host = Column(String(255), nullable=True)
    smtp_port = Column(Integer, nullable=True, default=587)
    smtp_username = Column(String(255), nullable=True)
    smtp_password = Column(String(500), nullable=True)  # Encrypted at rest
    smtp_use_tls = Column(Boolean, default=True, nullable=False)
    smtp_use_ssl = Column(Boolean, default=False, nullable=False)  # For port 465

    # =========================================================================
    # SendGrid Settings (used when provider=sendgrid, Business+ tier)
    # =========================================================================
    sendgrid_api_key = Column(String(500), nullable=True)  # Encrypted at rest

    # =========================================================================
    # Mailgun Settings (used when provider=mailgun, Business+ tier)
    # =========================================================================
    mailgun_api_key = Column(String(500), nullable=True)  # Encrypted at rest
    mailgun_domain = Column(String(255), nullable=True)

    # =========================================================================
    # Amazon SES Settings (used when provider=ses, Business+ tier)
    # =========================================================================
    ses_access_key_id = Column(String(100), nullable=True)
    ses_secret_access_key = Column(String(500), nullable=True)  # Encrypted at rest
    ses_region = Column(String(50), nullable=True, default="eu-west-1")

    # =========================================================================
    # Status & Verification
    # =========================================================================
    is_configured = Column(Boolean, default=False, nullable=False)  # Has complete config
    is_verified = Column(Boolean, default=False, nullable=False)  # Test email succeeded
    last_verified_at = Column(DateTime(timezone=True), nullable=True)
    verification_error = Column(Text, nullable=True)  # Last verification error message

    # =========================================================================
    # Relationship
    # =========================================================================
    store = relationship("Store", back_populates="email_settings")

    # =========================================================================
    # Indexes
    # =========================================================================
    __table_args__ = (
        Index("idx_store_email_settings_configured", "store_id", "is_configured"),
    )

    def __repr__(self) -> str:
        return f"<StoreEmailSettings(store_id={self.store_id}, provider='{self.provider}', from='{self.from_email}')>"

    # =========================================================================
    # Helper Methods
    # =========================================================================

    def is_smtp_configured(self) -> bool:
        """Check if SMTP settings are complete."""
        if self.provider != EmailProvider.SMTP.value:
            return False
        return bool(
            self.smtp_host
            and self.smtp_port
            and self.smtp_username
            and self.smtp_password
        )

    def is_sendgrid_configured(self) -> bool:
        """Check if SendGrid settings are complete."""
        if self.provider != EmailProvider.SENDGRID.value:
            return False
        return bool(self.sendgrid_api_key)

    def is_mailgun_configured(self) -> bool:
        """Check if Mailgun settings are complete."""
        if self.provider != EmailProvider.MAILGUN.value:
            return False
        return bool(self.mailgun_api_key and self.mailgun_domain)

    def is_ses_configured(self) -> bool:
        """Check if Amazon SES settings are complete."""
        if self.provider != EmailProvider.SES.value:
            return False
        return bool(
            self.ses_access_key_id
            and self.ses_secret_access_key
            and self.ses_region
        )

    def is_provider_configured(self) -> bool:
        """Check if the current provider is fully configured."""
        provider_checks = {
            EmailProvider.SMTP.value: self.is_smtp_configured,
            EmailProvider.SENDGRID.value: self.is_sendgrid_configured,
            EmailProvider.MAILGUN.value: self.is_mailgun_configured,
            EmailProvider.SES.value: self.is_ses_configured,
        }
        check_fn = provider_checks.get(self.provider)
        return check_fn() if check_fn else False

    def is_fully_configured(self) -> bool:
        """Check if email settings are fully configured (identity + provider)."""
        return bool(
            self.from_email
            and self.from_name
            and self.is_provider_configured()
        )

    def update_configuration_status(self) -> None:
        """Update the is_configured flag based on current settings."""
        self.is_configured = self.is_fully_configured()

    def mark_verified(self) -> None:
        """Mark settings as verified (test email succeeded)."""
        self.is_verified = True
        self.last_verified_at = datetime.now(UTC)
        self.verification_error = None

    def mark_verification_failed(self, error: str) -> None:
        """Mark settings as verification failed."""
        self.is_verified = False
        self.verification_error = error

    def requires_premium_tier(self) -> bool:
        """Check if current provider requires Business+ tier."""
        return self.provider in [p.value for p in PREMIUM_EMAIL_PROVIDERS]

    def to_dict(self) -> dict:
        """Convert to dictionary for API responses (excludes sensitive data)."""
        return {
            "id": self.id,
            "store_id": self.store_id,
            "from_email": self.from_email,
            "from_name": self.from_name,
            "reply_to_email": self.reply_to_email,
            "signature_text": self.signature_text,
            "signature_html": self.signature_html,
            "provider": self.provider,
            # SMTP (mask password)
            "smtp_host": self.smtp_host,
            "smtp_port": self.smtp_port,
            "smtp_username": self.smtp_username,
            "smtp_password_set": bool(self.smtp_password),
            "smtp_use_tls": self.smtp_use_tls,
            "smtp_use_ssl": self.smtp_use_ssl,
            # SendGrid (mask API key)
            "sendgrid_api_key_set": bool(self.sendgrid_api_key),
            # Mailgun (mask API key)
            "mailgun_api_key_set": bool(self.mailgun_api_key),
            "mailgun_domain": self.mailgun_domain,
            # SES (mask credentials)
            "ses_access_key_id_set": bool(self.ses_access_key_id),
            "ses_region": self.ses_region,
            # Status
            "is_configured": self.is_configured,
            "is_verified": self.is_verified,
            "last_verified_at": self.last_verified_at.isoformat() if self.last_verified_at else None,
            "verification_error": self.verification_error,
            "requires_premium_tier": self.requires_premium_tier(),
            # Timestamps
            "created_at": self.created_at.isoformat() if self.created_at else None,
            "updated_at": self.updated_at.isoformat() if self.updated_at else None,
        }


__all__ = ["EmailProvider", "PREMIUM_EMAIL_PROVIDERS", "StoreEmailSettings"]
