"""
Email Service
Multi-provider email service supporting SendGrid, AWS SES, and SMTP
"""
import os
import logging
from abc import ABC, abstractmethod
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
from typing import Optional, List, Dict, Any, Union
from datetime import datetime
from enum import Enum
import asyncio
import base64

# SMTP
import aiosmtplib

# AWS SES
import boto3
from botocore.exceptions import ClientError, NoCredentialsError

# SendGrid
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import (
    Mail, Email, To, Content, Attachment, FileContent,
    FileName, FileType, Disposition, Category, Asm,
    MailSettings, TrackingSettings, ClickTracking, OpenTracking
)

from app.config import settings
from app.templates.email_templates import EmailTemplates

logger = logging.getLogger(__name__)


class EmailProvider(str, Enum):
    """Available email providers"""
    SENDGRID = "sendgrid"
    AWS_SES = "ses"
    SMTP = "smtp"


class EmailConfig:
    """Email configuration from settings/environment"""

    # Provider selection
    DEFAULT_PROVIDER: str = os.getenv("EMAIL_PROVIDER", "smtp")

    # SendGrid
    SENDGRID_API_KEY: str = os.getenv("SENDGRID_API_KEY", "")
    SENDGRID_SANDBOX_MODE: bool = os.getenv("SENDGRID_SANDBOX_MODE", "false").lower() == "true"

    # AWS SES
    AWS_ACCESS_KEY_ID: str = os.getenv("AWS_ACCESS_KEY_ID", "")
    AWS_SECRET_ACCESS_KEY: str = os.getenv("AWS_SECRET_ACCESS_KEY", "")
    AWS_REGION: str = os.getenv("AWS_SES_REGION", os.getenv("AWS_REGION", "us-east-1"))
    SES_CONFIGURATION_SET: str = os.getenv("SES_CONFIGURATION_SET", "")

    # SMTP (fallback)
    SMTP_HOST: str = os.getenv("SMTP_HOST", "smtp.gmail.com")
    SMTP_PORT: int = int(os.getenv("SMTP_PORT", "587"))
    SMTP_USER: str = os.getenv("SMTP_USER", "")
    SMTP_PASSWORD: str = os.getenv("SMTP_PASSWORD", "")
    SMTP_USE_TLS: bool = os.getenv("SMTP_USE_TLS", "true").lower() == "true"

    # Sender defaults
    FROM_EMAIL: str = os.getenv("FROM_EMAIL", "noreply@ai360.com")
    FROM_NAME: str = os.getenv("FROM_NAME", "AI360 Solutions")
    REPLY_TO_EMAIL: str = os.getenv("REPLY_TO_EMAIL", "support@ai360.com")

    # Frontend URL
    FRONTEND_URL: str = getattr(settings, 'FRONTEND_URL', 'http://localhost:3000')


class EmailAttachment:
    """Email attachment model"""

    def __init__(
        self,
        filename: str,
        content: bytes,
        content_type: str = "application/octet-stream"
    ):
        self.filename = filename
        self.content = content
        self.content_type = content_type

    @classmethod
    def from_file(cls, filepath: str) -> "EmailAttachment":
        """Create attachment from file path"""
        import mimetypes
        filename = os.path.basename(filepath)
        content_type, _ = mimetypes.guess_type(filepath)

        with open(filepath, 'rb') as f:
            content = f.read()

        return cls(filename, content, content_type or "application/octet-stream")


class EmailResult:
    """Result of email send operation"""

    def __init__(
        self,
        success: bool,
        message_id: Optional[str] = None,
        provider: Optional[str] = None,
        error: Optional[str] = None
    ):
        self.success = success
        self.message_id = message_id
        self.provider = provider
        self.error = error
        self.timestamp = datetime.utcnow()

    def to_dict(self) -> Dict[str, Any]:
        return {
            "success": self.success,
            "message_id": self.message_id,
            "provider": self.provider,
            "error": self.error,
            "timestamp": self.timestamp.isoformat()
        }


class BaseEmailProvider(ABC):
    """Abstract base class for email providers"""

    @abstractmethod
    async def send(
        self,
        to_email: Union[str, List[str]],
        subject: str,
        html_content: str,
        text_content: Optional[str] = None,
        from_email: Optional[str] = None,
        from_name: Optional[str] = None,
        cc: Optional[List[str]] = None,
        bcc: Optional[List[str]] = None,
        reply_to: Optional[str] = None,
        attachments: Optional[List[EmailAttachment]] = None,
        categories: Optional[List[str]] = None,
        custom_args: Optional[Dict[str, str]] = None
    ) -> EmailResult:
        """Send an email"""
        pass

    @abstractmethod
    def is_configured(self) -> bool:
        """Check if provider is properly configured"""
        pass


class SendGridProvider(BaseEmailProvider):
    """SendGrid email provider"""

    def __init__(self):
        self.config = EmailConfig()
        self._client = None

    @property
    def client(self) -> SendGridAPIClient:
        if self._client is None:
            self._client = SendGridAPIClient(api_key=self.config.SENDGRID_API_KEY)
        return self._client

    def is_configured(self) -> bool:
        return bool(self.config.SENDGRID_API_KEY)

    async def send(
        self,
        to_email: Union[str, List[str]],
        subject: str,
        html_content: str,
        text_content: Optional[str] = None,
        from_email: Optional[str] = None,
        from_name: Optional[str] = None,
        cc: Optional[List[str]] = None,
        bcc: Optional[List[str]] = None,
        reply_to: Optional[str] = None,
        attachments: Optional[List[EmailAttachment]] = None,
        categories: Optional[List[str]] = None,
        custom_args: Optional[Dict[str, str]] = None
    ) -> EmailResult:
        try:
            # Build recipients list
            to_emails = [to_email] if isinstance(to_email, str) else to_email
            to_list = [To(email) for email in to_emails]

            # Create message
            from_addr = Email(
                from_email or self.config.FROM_EMAIL,
                from_name or self.config.FROM_NAME
            )

            message = Mail(
                from_email=from_addr,
                to_emails=to_list,
                subject=subject,
                html_content=Content("text/html", html_content)
            )

            # Add plain text if provided
            if text_content:
                message.add_content(Content("text/plain", text_content))

            # Add CC
            if cc:
                for email in cc:
                    message.add_cc(Email(email))

            # Add BCC
            if bcc:
                for email in bcc:
                    message.add_bcc(Email(email))

            # Add reply-to
            if reply_to:
                message.reply_to = Email(reply_to)

            # Add categories for tracking
            if categories:
                for cat in categories:
                    message.add_category(Category(cat))

            # Add custom arguments for webhooks
            if custom_args:
                for key, value in custom_args.items():
                    message.add_custom_arg({key: value})

            # Add attachments
            if attachments:
                for att in attachments:
                    attachment = Attachment()
                    attachment.file_content = FileContent(base64.b64encode(att.content).decode())
                    attachment.file_name = FileName(att.filename)
                    attachment.file_type = FileType(att.content_type)
                    attachment.disposition = Disposition("attachment")
                    message.add_attachment(attachment)

            # Configure tracking
            message.tracking_settings = TrackingSettings()
            message.tracking_settings.click_tracking = ClickTracking(True)
            message.tracking_settings.open_tracking = OpenTracking(True)

            # Sandbox mode for testing
            if self.config.SENDGRID_SANDBOX_MODE:
                message.mail_settings = MailSettings()
                message.mail_settings.sandbox_mode = True

            # Send using thread pool for async
            loop = asyncio.get_event_loop()
            response = await loop.run_in_executor(
                None,
                lambda: self.client.send(message)
            )

            message_id = response.headers.get('X-Message-Id', '')

            logger.info(f"SendGrid: Email sent to {to_email}, ID: {message_id}")

            return EmailResult(
                success=True,
                message_id=message_id,
                provider="sendgrid"
            )

        except Exception as e:
            logger.error(f"SendGrid error: {e}")
            return EmailResult(
                success=False,
                provider="sendgrid",
                error=str(e)
            )


class AWSSESProvider(BaseEmailProvider):
    """AWS SES email provider"""

    def __init__(self):
        self.config = EmailConfig()
        self._client = None

    @property
    def client(self):
        if self._client is None:
            self._client = boto3.client(
                'ses',
                region_name=self.config.AWS_REGION,
                aws_access_key_id=self.config.AWS_ACCESS_KEY_ID,
                aws_secret_access_key=self.config.AWS_SECRET_ACCESS_KEY
            )
        return self._client

    def is_configured(self) -> bool:
        return bool(self.config.AWS_ACCESS_KEY_ID and self.config.AWS_SECRET_ACCESS_KEY)

    async def send(
        self,
        to_email: Union[str, List[str]],
        subject: str,
        html_content: str,
        text_content: Optional[str] = None,
        from_email: Optional[str] = None,
        from_name: Optional[str] = None,
        cc: Optional[List[str]] = None,
        bcc: Optional[List[str]] = None,
        reply_to: Optional[str] = None,
        attachments: Optional[List[EmailAttachment]] = None,
        categories: Optional[List[str]] = None,
        custom_args: Optional[Dict[str, str]] = None
    ) -> EmailResult:
        try:
            # Build recipients list
            to_emails = [to_email] if isinstance(to_email, str) else to_email

            # Format sender
            sender = from_email or self.config.FROM_EMAIL
            if from_name or self.config.FROM_NAME:
                sender = f"{from_name or self.config.FROM_NAME} <{sender}>"

            # If attachments, use raw email
            if attachments:
                return await self._send_raw_email(
                    to_emails=to_emails,
                    subject=subject,
                    html_content=html_content,
                    text_content=text_content,
                    sender=sender,
                    cc=cc,
                    bcc=bcc,
                    reply_to=reply_to,
                    attachments=attachments
                )

            # Build destination
            destination = {'ToAddresses': to_emails}
            if cc:
                destination['CcAddresses'] = cc
            if bcc:
                destination['BccAddresses'] = bcc

            # Build message
            message = {
                'Subject': {'Data': subject, 'Charset': 'UTF-8'},
                'Body': {
                    'Html': {'Data': html_content, 'Charset': 'UTF-8'}
                }
            }

            if text_content:
                message['Body']['Text'] = {'Data': text_content, 'Charset': 'UTF-8'}

            # Build send request
            send_args = {
                'Source': sender,
                'Destination': destination,
                'Message': message
            }

            if reply_to:
                send_args['ReplyToAddresses'] = [reply_to]

            if self.config.SES_CONFIGURATION_SET:
                send_args['ConfigurationSetName'] = self.config.SES_CONFIGURATION_SET

            # Add tags for tracking
            if categories:
                send_args['Tags'] = [
                    {'Name': 'category', 'Value': cat}
                    for cat in categories[:10]  # SES limits to 10 tags
                ]

            # Send using thread pool
            loop = asyncio.get_event_loop()
            response = await loop.run_in_executor(
                None,
                lambda: self.client.send_email(**send_args)
            )

            message_id = response.get('MessageId', '')

            logger.info(f"AWS SES: Email sent to {to_email}, ID: {message_id}")

            return EmailResult(
                success=True,
                message_id=message_id,
                provider="ses"
            )

        except NoCredentialsError:
            logger.error("AWS SES: No credentials configured")
            return EmailResult(
                success=False,
                provider="ses",
                error="AWS credentials not configured"
            )
        except ClientError as e:
            error_code = e.response['Error']['Code']
            error_msg = e.response['Error']['Message']
            logger.error(f"AWS SES error ({error_code}): {error_msg}")
            return EmailResult(
                success=False,
                provider="ses",
                error=f"{error_code}: {error_msg}"
            )
        except Exception as e:
            logger.error(f"AWS SES error: {e}")
            return EmailResult(
                success=False,
                provider="ses",
                error=str(e)
            )

    async def _send_raw_email(
        self,
        to_emails: List[str],
        subject: str,
        html_content: str,
        text_content: Optional[str],
        sender: str,
        cc: Optional[List[str]],
        bcc: Optional[List[str]],
        reply_to: Optional[str],
        attachments: List[EmailAttachment]
    ) -> EmailResult:
        """Send raw email with attachments"""
        try:
            # Build MIME message
            msg = MIMEMultipart('mixed')
            msg['Subject'] = subject
            msg['From'] = sender
            msg['To'] = ', '.join(to_emails)

            if cc:
                msg['Cc'] = ', '.join(cc)
            if reply_to:
                msg['Reply-To'] = reply_to

            # Create alternative part for text/html
            msg_body = MIMEMultipart('alternative')

            if text_content:
                msg_body.attach(MIMEText(text_content, 'plain', 'utf-8'))

            msg_body.attach(MIMEText(html_content, 'html', 'utf-8'))
            msg.attach(msg_body)

            # Add attachments
            for att in attachments:
                part = MIMEBase(*att.content_type.split('/'))
                part.set_payload(att.content)
                encoders.encode_base64(part)
                part.add_header(
                    'Content-Disposition',
                    f'attachment; filename="{att.filename}"'
                )
                msg.attach(part)

            # Build destinations
            destinations = to_emails[:]
            if cc:
                destinations.extend(cc)
            if bcc:
                destinations.extend(bcc)

            # Send raw email
            loop = asyncio.get_event_loop()
            response = await loop.run_in_executor(
                None,
                lambda: self.client.send_raw_email(
                    Source=sender,
                    Destinations=destinations,
                    RawMessage={'Data': msg.as_string()}
                )
            )

            message_id = response.get('MessageId', '')

            return EmailResult(
                success=True,
                message_id=message_id,
                provider="ses"
            )

        except Exception as e:
            logger.error(f"AWS SES raw email error: {e}")
            return EmailResult(
                success=False,
                provider="ses",
                error=str(e)
            )

    async def verify_email_identity(self, email: str) -> bool:
        """Verify an email identity in SES (for sandbox mode)"""
        try:
            loop = asyncio.get_event_loop()
            await loop.run_in_executor(
                None,
                lambda: self.client.verify_email_identity(EmailAddress=email)
            )
            return True
        except Exception as e:
            logger.error(f"SES verify identity error: {e}")
            return False

    async def get_send_quota(self) -> Dict[str, Any]:
        """Get SES sending quota"""
        try:
            loop = asyncio.get_event_loop()
            response = await loop.run_in_executor(
                None,
                lambda: self.client.get_send_quota()
            )
            return {
                "max_24_hour_send": response['Max24HourSend'],
                "max_send_rate": response['MaxSendRate'],
                "sent_last_24_hours": response['SentLast24Hours']
            }
        except Exception as e:
            logger.error(f"SES get quota error: {e}")
            return {}


class SMTPProvider(BaseEmailProvider):
    """SMTP email provider (fallback)"""

    def __init__(self):
        self.config = EmailConfig()

    def is_configured(self) -> bool:
        return bool(self.config.SMTP_HOST and self.config.SMTP_USER)

    async def send(
        self,
        to_email: Union[str, List[str]],
        subject: str,
        html_content: str,
        text_content: Optional[str] = None,
        from_email: Optional[str] = None,
        from_name: Optional[str] = None,
        cc: Optional[List[str]] = None,
        bcc: Optional[List[str]] = None,
        reply_to: Optional[str] = None,
        attachments: Optional[List[EmailAttachment]] = None,
        categories: Optional[List[str]] = None,
        custom_args: Optional[Dict[str, str]] = None
    ) -> EmailResult:
        try:
            # Build recipients list
            to_emails = [to_email] if isinstance(to_email, str) else to_email

            # Create message
            if attachments:
                msg = MIMEMultipart('mixed')
                msg_body = MIMEMultipart('alternative')

                if text_content:
                    msg_body.attach(MIMEText(text_content, 'plain'))
                msg_body.attach(MIMEText(html_content, 'html'))

                msg.attach(msg_body)

                # Add attachments
                for att in attachments:
                    part = MIMEBase(*att.content_type.split('/'))
                    part.set_payload(att.content)
                    encoders.encode_base64(part)
                    part.add_header(
                        'Content-Disposition',
                        f'attachment; filename="{att.filename}"'
                    )
                    msg.attach(part)
            else:
                msg = MIMEMultipart('alternative')
                if text_content:
                    msg.attach(MIMEText(text_content, 'plain'))
                msg.attach(MIMEText(html_content, 'html'))

            # Set headers
            sender_name = from_name or self.config.FROM_NAME
            sender_email = from_email or self.config.FROM_EMAIL

            msg['Subject'] = subject
            msg['From'] = f"{sender_name} <{sender_email}>"
            msg['To'] = ', '.join(to_emails)

            if cc:
                msg['Cc'] = ', '.join(cc)
            if reply_to:
                msg['Reply-To'] = reply_to

            # Build all recipients
            recipients = to_emails[:]
            if cc:
                recipients.extend(cc)
            if bcc:
                recipients.extend(bcc)

            # Send
            await aiosmtplib.send(
                msg,
                hostname=self.config.SMTP_HOST,
                port=self.config.SMTP_PORT,
                username=self.config.SMTP_USER,
                password=self.config.SMTP_PASSWORD,
                start_tls=self.config.SMTP_USE_TLS
            )

            logger.info(f"SMTP: Email sent to {to_email}")

            return EmailResult(
                success=True,
                message_id=None,  # SMTP doesn't return message ID
                provider="smtp"
            )

        except Exception as e:
            logger.error(f"SMTP error: {e}")
            return EmailResult(
                success=False,
                provider="smtp",
                error=str(e)
            )


class EmailService:
    """
    Multi-provider email service
    Supports SendGrid, AWS SES, and SMTP with automatic fallback
    """

    def __init__(self, provider: Optional[EmailProvider] = None):
        self.config = EmailConfig()
        self.frontend_url = self.config.FRONTEND_URL

        # Initialize providers
        self._sendgrid = SendGridProvider()
        self._ses = AWSSESProvider()
        self._smtp = SMTPProvider()

        # Set default provider
        if provider:
            self.default_provider = provider
        else:
            self.default_provider = EmailProvider(self.config.DEFAULT_PROVIDER)

    def _get_provider(self, provider: Optional[EmailProvider] = None) -> BaseEmailProvider:
        """Get the appropriate email provider"""
        use_provider = provider or self.default_provider

        if use_provider == EmailProvider.SENDGRID and self._sendgrid.is_configured():
            return self._sendgrid
        elif use_provider == EmailProvider.AWS_SES and self._ses.is_configured():
            return self._ses
        elif use_provider == EmailProvider.SMTP and self._smtp.is_configured():
            return self._smtp

        # Fallback chain: SendGrid -> SES -> SMTP
        if self._sendgrid.is_configured():
            return self._sendgrid
        elif self._ses.is_configured():
            return self._ses
        elif self._smtp.is_configured():
            return self._smtp

        raise ValueError("No email provider configured")

    async def send_email(
        self,
        to_email: Union[str, List[str]],
        subject: str,
        html_content: str,
        text_content: Optional[str] = None,
        cc: Optional[List[str]] = None,
        bcc: Optional[List[str]] = None,
        reply_to: Optional[str] = None,
        attachments: Optional[List[EmailAttachment]] = None,
        categories: Optional[List[str]] = None,
        provider: Optional[EmailProvider] = None
    ) -> EmailResult:
        """
        Send an email using the configured provider

        Args:
            to_email: Recipient(s)
            subject: Email subject
            html_content: HTML body
            text_content: Plain text body (optional)
            cc: CC recipients
            bcc: BCC recipients
            reply_to: Reply-to address
            attachments: List of attachments
            categories: Categories for tracking
            provider: Specific provider to use

        Returns:
            EmailResult with success status and message ID
        """
        email_provider = self._get_provider(provider)

        result = await email_provider.send(
            to_email=to_email,
            subject=subject,
            html_content=html_content,
            text_content=text_content,
            cc=cc,
            bcc=bcc,
            reply_to=reply_to,
            attachments=attachments,
            categories=categories
        )

        return result

    # ============================================================
    # CONVENIENCE METHODS (Using templates)
    # ============================================================

    async def send_welcome_email(
        self,
        to_email: str,
        user_name: str,
        trial_days: int = 14
    ) -> EmailResult:
        """Send welcome email to new user"""
        context = {
            'user_name': user_name,
            'dashboard_url': f"{self.frontend_url}/dashboard",
            'trial_days': trial_days,
            'year': datetime.now().year
        }

        html_content = EmailTemplates.welcome_new_user(context)

        return await self.send_email(
            to_email=to_email,
            subject="Welcome to AI360 Solutions! 🎉",
            html_content=html_content,
            categories=["welcome", "onboarding"]
        )

    async def send_team_invite_email(
        self,
        to_email: str,
        user_name: str,
        inviter_name: str,
        company_name: str,
        role: str,
        invite_token: str
    ) -> EmailResult:
        """Send team invitation email"""
        context = {
            'user_name': user_name,
            'inviter_name': inviter_name,
            'company_name': company_name,
            'role': role,
            'dashboard_url': f"{self.frontend_url}/accept-invite?token={invite_token}",
            'year': datetime.now().year
        }

        html_content = EmailTemplates.welcome_team_member(context)

        return await self.send_email(
            to_email=to_email,
            subject=f"You've been invited to join {company_name} on AI360",
            html_content=html_content,
            categories=["team-invite", "onboarding"]
        )

    async def send_password_reset_email(
        self,
        to_email: str,
        user_name: str,
        reset_token: str
    ) -> EmailResult:
        """Send password reset email"""
        reset_link = f"{self.frontend_url}/reset-password?token={reset_token}"

        html_content = EmailTemplates._base_template(f"""
        <div class="container">
            <div class="header">
                <div class="header-icon">🔐</div>
                <h1>Reset Your Password</h1>
                <p>We received a request to reset your password</p>
            </div>
            <div class="content">
                <p>Hi <strong>{user_name}</strong>,</p>

                <p>We received a request to reset the password for your AI360 account. Click the button below to create a new password:</p>

                <div class="button-container">
                    <a href="{reset_link}" class="button">Reset Password →</a>
                </div>

                <div class="info-box">
                    <strong>⏰ Link expires in:</strong> 1 hour
                </div>

                <p>If the button doesn't work, copy and paste this link into your browser:</p>
                <p style="word-break: break-all; color: #3b82f6; font-size: 14px;">{reset_link}</p>

                <hr class="divider">

                <p style="color: #6b7280; font-size: 14px;">If you didn't request a password reset, you can safely ignore this email. Your password will remain unchanged.</p>

                <p>Thanks,<br><strong>AI360 Solutions Team</strong></p>
            </div>
            <div class="footer">
                <p>© {datetime.now().year} AI360 Solutions. All rights reserved.</p>
            </div>
        </div>
        """, "Reset your AI360 password")

        return await self.send_email(
            to_email=to_email,
            subject="Reset Your Password - AI360",
            html_content=html_content,
            categories=["password-reset", "security"]
        )

    async def send_password_changed_email(
        self,
        to_email: str,
        user_name: str
    ) -> EmailResult:
        """Send confirmation that password was changed"""
        html_content = EmailTemplates._base_template(f"""
        <div class="container">
            <div class="header" style="background: linear-gradient(135deg, #10b981 0%, #059669 100%);">
                <div class="header-icon">✅</div>
                <h1>Password Changed</h1>
                <p>Your password has been updated</p>
            </div>
            <div class="content">
                <p>Hi <strong>{user_name}</strong>,</p>

                <p>Your password has been successfully changed.</p>

                <div class="success-box">
                    <strong>✓ Password Updated</strong><br>
                    Your new password is now active. You may need to log in again on your devices.
                </div>

                <div class="danger-box">
                    <strong>⚠️ Didn't make this change?</strong><br>
                    If you didn't change your password, please contact our support team immediately at <a href="mailto:support@ai360.com">support@ai360.com</a>
                </div>

                <p>Thanks,<br><strong>AI360 Solutions Team</strong></p>
            </div>
            <div class="footer">
                <p>© {datetime.now().year} AI360 Solutions. All rights reserved.</p>
            </div>
        </div>
        """, "Your AI360 password has been changed")

        return await self.send_email(
            to_email=to_email,
            subject="Your Password Has Been Changed - AI360",
            html_content=html_content,
            categories=["password-changed", "security"]
        )

    async def send_verification_email(
        self,
        to_email: str,
        user_name: str,
        verification_token: str
    ) -> EmailResult:
        """Send email verification link"""
        verification_link = f"{self.frontend_url}/verify-email?token={verification_token}"

        html_content = EmailTemplates._base_template(f"""
        <div class="container">
            <div class="header" style="background: linear-gradient(135deg, #10b981 0%, #059669 100%);">
                <div class="header-icon">✉️</div>
                <h1>Verify Your Email</h1>
                <p>One more step to get started</p>
            </div>
            <div class="content">
                <p>Hi <strong>{user_name}</strong>,</p>

                <p>Please verify your email address to complete your registration and unlock all features.</p>

                <div class="button-container">
                    <a href="{verification_link}" class="button button-secondary">Verify Email →</a>
                </div>

                <div class="info-box">
                    <strong>⏰ This link will expire in 24 hours</strong>
                </div>

                <p>If the button doesn't work, copy and paste this link into your browser:</p>
                <p style="word-break: break-all; color: #3b82f6; font-size: 14px;">{verification_link}</p>

                <p>Thanks,<br><strong>AI360 Solutions Team</strong></p>
            </div>
            <div class="footer">
                <p>© {datetime.now().year} AI360 Solutions. All rights reserved.</p>
            </div>
        </div>
        """, "Verify your email address for AI360")

        return await self.send_email(
            to_email=to_email,
            subject="Verify Your Email - AI360",
            html_content=html_content,
            categories=["email-verification", "onboarding"]
        )

    async def send_invoice_email(
        self,
        to_email: str,
        user_name: str,
        invoice_number: str,
        amount: float,
        tax_amount: float,
        total_amount: float,
        due_date: str,
        billing_period: str,
        plan_name: str,
        line_items: List[Dict[str, Any]] = None,
        currency: str = "INR"
    ) -> EmailResult:
        """Send invoice created email"""
        context = {
            'user_name': user_name,
            'invoice_number': invoice_number,
            'amount': amount,
            'tax_amount': tax_amount,
            'total_amount': total_amount,
            'currency': currency,
            'due_date': due_date,
            'billing_period': billing_period,
            'plan_name': plan_name,
            'line_items': line_items or [],
            'invoice_url': f"{self.frontend_url}/invoices/{invoice_number}",
            'pay_url': f"{self.frontend_url}/invoices/{invoice_number}/pay",
            'year': datetime.now().year
        }

        html_content = EmailTemplates.invoice_created(context)

        return await self.send_email(
            to_email=to_email,
            subject=f"Invoice {invoice_number} - AI360 Solutions",
            html_content=html_content,
            categories=["invoice", "billing"]
        )

    async def send_payment_confirmation_email(
        self,
        to_email: str,
        user_name: str,
        invoice_number: str,
        amount: float,
        payment_method: str,
        transaction_id: str,
        next_billing_date: str,
        currency: str = "INR"
    ) -> EmailResult:
        """Send payment confirmation email"""
        context = {
            'user_name': user_name,
            'invoice_number': invoice_number,
            'amount': amount,
            'currency': currency,
            'payment_method': payment_method,
            'transaction_id': transaction_id,
            'receipt_url': f"{self.frontend_url}/invoices/{invoice_number}/receipt",
            'next_billing_date': next_billing_date,
            'year': datetime.now().year
        }

        html_content = EmailTemplates.invoice_paid(context)

        return await self.send_email(
            to_email=to_email,
            subject=f"Payment Confirmed - Invoice {invoice_number}",
            html_content=html_content,
            categories=["payment", "billing"]
        )

    async def send_invoice_overdue_email(
        self,
        to_email: str,
        user_name: str,
        invoice_number: str,
        amount: float,
        due_date: str,
        days_overdue: int,
        currency: str = "INR"
    ) -> EmailResult:
        """Send invoice overdue reminder"""
        context = {
            'user_name': user_name,
            'invoice_number': invoice_number,
            'amount': amount,
            'currency': currency,
            'due_date': due_date,
            'days_overdue': days_overdue,
            'pay_url': f"{self.frontend_url}/invoices/{invoice_number}/pay",
            'year': datetime.now().year
        }

        html_content = EmailTemplates.invoice_overdue(context)

        return await self.send_email(
            to_email=to_email,
            subject=f"⚠️ Payment Overdue - Invoice {invoice_number}",
            html_content=html_content,
            categories=["overdue", "billing"]
        )

    async def send_usage_warning_email(
        self,
        to_email: str,
        user_name: str,
        resource_type: str,
        current_usage: int,
        limit: int,
        percentage: int
    ) -> EmailResult:
        """Send usage limit warning email"""
        context = {
            'user_name': user_name,
            'resource_type': resource_type,
            'current_usage': current_usage,
            'limit': limit,
            'percentage': percentage,
            'upgrade_url': f"{self.frontend_url}/billing/upgrade",
            'year': datetime.now().year
        }

        html_content = EmailTemplates.usage_limit_warning(context)

        return await self.send_email(
            to_email=to_email,
            subject=f"⚠️ Usage Alert: {percentage}% of {resource_type} limit used",
            html_content=html_content,
            categories=["usage-warning", "alert"]
        )

    async def send_usage_limit_reached_email(
        self,
        to_email: str,
        user_name: str,
        resource_type: str,
        limit: int,
        reset_date: str
    ) -> EmailResult:
        """Send usage limit reached notification"""
        context = {
            'user_name': user_name,
            'resource_type': resource_type,
            'limit': limit,
            'reset_date': reset_date,
            'upgrade_url': f"{self.frontend_url}/billing/upgrade",
            'year': datetime.now().year
        }

        html_content = EmailTemplates.usage_limit_reached(context)

        return await self.send_email(
            to_email=to_email,
            subject=f"🚫 Limit Reached: Your {resource_type} limit has been reached",
            html_content=html_content,
            categories=["usage-limit", "alert"]
        )

    async def send_subscription_expiring_email(
        self,
        to_email: str,
        user_name: str,
        plan_name: str,
        expiry_date: str,
        days_left: int
    ) -> EmailResult:
        """Send subscription expiring alert"""
        context = {
            'user_name': user_name,
            'plan_name': plan_name,
            'expiry_date': expiry_date,
            'days_left': days_left,
            'renew_url': f"{self.frontend_url}/billing/renew",
            'year': datetime.now().year
        }

        html_content = EmailTemplates.subscription_expiring(context)

        return await self.send_email(
            to_email=to_email,
            subject=f"📅 Your subscription expires in {days_left} days",
            html_content=html_content,
            categories=["subscription", "alert"]
        )

    async def send_subscription_cancelled_email(
        self,
        to_email: str,
        user_name: str,
        plan_name: str,
        end_date: str
    ) -> EmailResult:
        """Send subscription cancelled confirmation"""
        context = {
            'user_name': user_name,
            'plan_name': plan_name,
            'end_date': end_date,
            'feedback_url': f"{self.frontend_url}/feedback",
            'reactivate_url': f"{self.frontend_url}/billing/reactivate",
            'year': datetime.now().year
        }

        html_content = EmailTemplates.subscription_cancelled(context)

        return await self.send_email(
            to_email=to_email,
            subject="We're sorry to see you go - AI360",
            html_content=html_content,
            categories=["subscription-cancelled"]
        )

    async def send_new_login_alert(
        self,
        to_email: str,
        user_name: str,
        login_time: str,
        ip_address: str,
        location: str,
        device: str,
        browser: str
    ) -> EmailResult:
        """Send new login security alert"""
        context = {
            'user_name': user_name,
            'login_time': login_time,
            'ip_address': ip_address,
            'location': location,
            'device': device,
            'browser': browser,
            'secure_account_url': f"{self.frontend_url}/account/security",
            'year': datetime.now().year
        }

        html_content = EmailTemplates.security_alert_login(context)

        return await self.send_email(
            to_email=to_email,
            subject="🔐 New login to your AI360 account",
            html_content=html_content,
            categories=["security", "login-alert"]
        )

    async def send_api_key_created_alert(
        self,
        to_email: str,
        user_name: str,
        key_name: str,
        created_by: str,
        permissions: List[str]
    ) -> EmailResult:
        """Send API key created notification"""
        context = {
            'user_name': user_name,
            'key_name': key_name,
            'created_by': created_by,
            'created_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'permissions': permissions,
            'manage_keys_url': f"{self.frontend_url}/settings/api-keys",
            'year': datetime.now().year
        }

        html_content = EmailTemplates.api_key_created(context)

        return await self.send_email(
            to_email=to_email,
            subject=f"🔑 New API key created: {key_name}",
            html_content=html_content,
            categories=["security", "api-key"]
        )

    async def send_weekly_report_email(
        self,
        to_email: str,
        user_name: str,
        week_range: str,
        total_conversations: int,
        total_messages: int,
        avg_response_time: str,
        satisfaction_rate: int,
        top_topics: List[Dict[str, Any]] = None
    ) -> EmailResult:
        """Send weekly analytics report"""
        context = {
            'user_name': user_name,
            'week_range': week_range,
            'total_conversations': total_conversations,
            'total_messages': total_messages,
            'avg_response_time': avg_response_time,
            'satisfaction_rate': satisfaction_rate,
            'top_topics': top_topics or [],
            'dashboard_url': f"{self.frontend_url}/dashboard/analytics",
            'year': datetime.now().year
        }

        html_content = EmailTemplates.weekly_report(context)

        return await self.send_email(
            to_email=to_email,
            subject=f"📈 Your Weekly AI360 Report - {week_range}",
            html_content=html_content,
            categories=["report", "weekly"]
        )

    # ============================================================
    # BULK EMAIL OPERATIONS
    # ============================================================

    async def send_bulk_email(
        self,
        recipients: List[Dict[str, Any]],
        subject: str,
        html_template: str,
        categories: Optional[List[str]] = None
    ) -> Dict[str, Any]:
        """
        Send bulk emails with personalization

        Args:
            recipients: List of dicts with 'email' and any personalization fields
            subject: Email subject (can include {field} placeholders)
            html_template: HTML template with {field} placeholders
            categories: Tracking categories

        Returns:
            Summary of sent/failed emails
        """
        results = {
            "total": len(recipients),
            "sent": 0,
            "failed": 0,
            "errors": []
        }

        for recipient in recipients:
            try:
                email = recipient.get('email')
                if not email:
                    continue

                # Personalize content
                personalized_subject = subject.format(**recipient)
                personalized_html = html_template.format(**recipient)

                result = await self.send_email(
                    to_email=email,
                    subject=personalized_subject,
                    html_content=personalized_html,
                    categories=categories
                )

                if result.success:
                    results["sent"] += 1
                else:
                    results["failed"] += 1
                    results["errors"].append({
                        "email": email,
                        "error": result.error
                    })

            except Exception as e:
                results["failed"] += 1
                results["errors"].append({
                    "email": recipient.get('email', 'unknown'),
                    "error": str(e)
                })

        return results


# Singleton instance
email_service = EmailService()
