"""
邮件通知服务

支持发送告警通知、额度预警等邮件。

功能:
- 邮件模板引擎: 变量替换渲染邮件内容
- 邮件内容生成: 告警通知、额度预警邮件生成
- 邮件发送: 支持真实SMTP和模拟模式
- 邮件队列管理: 批量添加和发送
- 错误处理和重试: 自动重试机制
"""
from __future__ import annotations

import logging
import re
import smtplib
import time
import uuid
from dataclasses import dataclass, field
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
from typing import Any

logger = logging.getLogger(__name__)


EMAIL_TEMPLATES = {
    "alert_notification": {
        "subject": "[GEO平台] 告警通知：{alert_type}",
        "body_html": """
        <h2>告警通知</h2>
        <p>品牌：<strong>{brand_name}</strong></p>
        <p>告警类型：{alert_type}</p>
        <p>严重程度：{severity}</p>
        <p>详情：{description}</p>
        <p>时间：{timestamp}</p>
        """,
        "body_text": "告警通知 - 品牌：{brand_name}, 类型：{alert_type},  severity：{severity}"
    },
    "quota_warning": {
        "subject": "[GEO平台] 额度预警：{quota_type}",
        "body_html": """
        <h2>额度预警</h2>
        <p>您的{quota_type}使用量已达到{usage_percentage}%</p>
        <p>已使用：{used} / 总额度：{limit}</p>
        <p>建议操作：{recommended_action}</p>
        """,
        "body_text": "额度预警 - {quota_type}使用量：{usage_percentage}%"
    }
}


@dataclass
class EmailMessage:
    to: str
    subject: str
    body_html: str
    body_text: str
    attachments: list[dict] = field(default_factory=list)
    metadata: dict = field(default_factory=dict)


@dataclass
class EmailSendResult:
    success: bool
    message_id: str | None
    error: str | None
    retry_count: int


class EmailService:
    """邮件通知服务
    
    提供邮件模板渲染、内容生成、发送（支持模拟模式）、队列管理等功能。
    """

    def __init__(
        self,
        simulate_mode: bool = True,
        smtp_host: str = "localhost",
        smtp_port: int = 587,
        smtp_user: str = "",
        smtp_password: str = "",
        max_retries: int = 3,
    ):
        self.simulate_mode = simulate_mode
        self.smtp_host = smtp_host
        self.smtp_port = smtp_port
        self.smtp_user = smtp_user
        self.smtp_password = smtp_password
        self.max_retries = max_retries
        self._queue: list[EmailMessage] = []

    def validate_email(self, email: str) -> bool:
        """验证邮箱地址格式
        
        Args:
            email: 邮箱地址
            
        Returns:
            是否为有效邮箱地址
        """
        if not email:
            return False
        pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
        return bool(re.match(pattern, email))

    def _safe_format(self, template: str, variables: dict[str, Any]) -> str:
        """安全格式化模板，缺失变量时保留原占位符
        
        Args:
            template: 模板字符串
            variables: 变量字典
            
        Returns:
            格式化后的字符串
        """
        try:
            return template.format(**variables)
        except KeyError:
            result = template
            for key, value in variables.items():
                result = result.replace("{" + key + "}", str(value))
            return result

    def render_template(
        self,
        template_name: str,
        to: str,
        variables: dict[str, Any],
    ) -> EmailMessage:
        """渲染邮件模板
        
        Args:
            template_name: 模板名称
            to: 收件人邮箱
            variables: 模板变量
            
        Returns:
            EmailMessage邮件消息对象
            
        Raises:
            ValueError: 模板不存在
        """
        if template_name not in EMAIL_TEMPLATES:
            raise ValueError(f"模板不存在: {template_name}")
        
        template = EMAIL_TEMPLATES[template_name]
        
        subject = self._safe_format(template["subject"], variables)
        body_html = self._safe_format(template["body_html"], variables)
        body_text = self._safe_format(template["body_text"], variables)
        
        return EmailMessage(
            to=to,
            subject=subject,
            body_html=body_html,
            body_text=body_text,
            metadata=variables,
        )

    def generate_alert_email(
        self,
        to: str,
        alert_type: str,
        brand_name: str,
        severity: str,
        description: str,
        timestamp: str,
    ) -> EmailMessage:
        """生成告警通知邮件
        
        Args:
            to: 收件人邮箱
            alert_type: 告警类型
            brand_name: 品牌名称
            severity: 严重程度
            description: 告警详情
            timestamp: 时间戳
            
        Returns:
            EmailMessage邮件消息对象
        """
        variables = {
            "alert_type": alert_type,
            "brand_name": brand_name,
            "severity": severity,
            "description": description,
            "timestamp": timestamp,
        }
        return self.render_template("alert_notification", to, variables)

    def generate_quota_warning_email(
        self,
        to: str,
        quota_type: str,
        usage_percentage: int,
        used: int,
        limit: int,
        recommended_action: str,
    ) -> EmailMessage:
        """生成额度预警邮件
        
        Args:
            to: 收件人邮箱
            quota_type: 额度类型
            usage_percentage: 使用百分比
            used: 已使用量
            limit: 总额度
            recommended_action: 建议操作
            
        Returns:
            EmailMessage邮件消息对象
        """
        variables = {
            "quota_type": quota_type,
            "usage_percentage": usage_percentage,
            "used": used,
            "limit": limit,
            "recommended_action": recommended_action,
        }
        return self.render_template("quota_warning", to, variables)

    def add_attachment(self, msg: EmailMessage, filename: str, content: bytes) -> None:
        """添加附件到邮件
        
        Args:
            msg: 邮件消息对象
            filename: 附件文件名
            content: 附件内容
        """
        msg.attachments.append({
            "filename": filename,
            "content": content,
        })

    def _create_mime_message(self, msg: EmailMessage) -> MIMEMultipart:
        """创建MIME邮件对象
        
        Args:
            msg: EmailMessage对象
            
        Returns:
            MIMEMultipart MIME邮件对象
        """
        mime_msg = MIMEMultipart()
        mime_msg["From"] = self.smtp_user
        mime_msg["To"] = msg.to
        mime_msg["Subject"] = msg.subject
        
        mime_msg.attach(MIMEText(msg.body_html, "html", "utf-8"))
        mime_msg.attach(MIMEText(msg.body_text, "plain", "utf-8"))
        
        for attachment in msg.attachments:
            part = MIMEBase("application", "octet-stream")
            part.set_payload(attachment["content"])
            encoders.encode_base64(part)
            part.add_header(
                "Content-Disposition",
                f'attachment; filename="{attachment["filename"]}"',
            )
            mime_msg.attach(part)
        
        return mime_msg

    def send_email(self, msg: EmailMessage) -> EmailSendResult:
        """发送邮件
        
        Args:
            msg: EmailMessage邮件消息对象
            
        Returns:
            EmailSendResult发送结果对象
        """
        if not self.validate_email(msg.to):
            logger.warning(f"无效的邮箱地址: {msg.to}")
            return EmailSendResult(
                success=False,
                message_id=None,
                error=f"无效的邮箱地址: {msg.to}",
                retry_count=0,
            )
        
        if self.simulate_mode:
            message_id = f"sim_{uuid.uuid4().hex[:8]}"
            logger.info(f"[模拟模式] 邮件发送成功: {msg.to}, ID: {message_id}")
            return EmailSendResult(
                success=True,
                message_id=message_id,
                error=None,
                retry_count=0,
            )
        
        retry_count = 0
        last_error = None
        
        while retry_count <= self.max_retries:
            try:
                logger.info(f"尝试发送邮件到 {msg.to} (尝试 {retry_count + 1}/{self.max_retries + 1})")
                server = smtplib.SMTP(self.smtp_host, self.smtp_port)
                server.starttls()
                server.login(self.smtp_user, self.smtp_password)
                
                mime_msg = self._create_mime_message(msg)
                server.send_message(mime_msg)
                server.quit()
                
                message_id = f"smtp_{uuid.uuid4().hex[:8]}"
                logger.info(f"邮件发送成功: {msg.to}, ID: {message_id}")
                return EmailSendResult(
                    success=True,
                    message_id=message_id,
                    error=None,
                    retry_count=retry_count,
                )
            except smtplib.SMTPException as e:
                last_error = f"SMTP错误: {str(e)}"
                logger.error(f"SMTP错误 (尝试 {retry_count + 1}/{self.max_retries + 1}): {e}")
                retry_count += 1
                if retry_count <= self.max_retries:
                    time.sleep(1 * retry_count)
            except Exception as e:
                last_error = str(e)
                logger.error(f"邮件发送失败 (尝试 {retry_count + 1}/{self.max_retries + 1}): {e}")
                retry_count += 1
                if retry_count <= self.max_retries:
                    time.sleep(1 * retry_count)
        
        logger.error(f"邮件发送最终失败，已重试 {retry_count} 次: {msg.to}, 错误: {last_error}")
        return EmailSendResult(
            success=False,
            message_id=None,
            error=last_error,
            retry_count=retry_count,
        )

    def add_to_queue(self, msg: EmailMessage) -> None:
        """添加邮件到队列
        
        Args:
            msg: EmailMessage邮件消息对象
        """
        self._queue.append(msg)
        logger.debug(f"邮件已添加到队列: {msg.to}, 队列长度: {len(self._queue)}")

    def get_queue(self) -> list[EmailMessage]:
        """获取队列中的邮件
        
        Returns:
            邮件消息列表
        """
        return self._queue.copy()

    def clear_queue(self) -> None:
        """清空队列"""
        count = len(self._queue)
        self._queue.clear()
        logger.info(f"队列已清空，移除了 {count} 封邮件")

    def send_queue(self) -> list[EmailSendResult]:
        """发送队列中的所有邮件
        
        Returns:
            发送结果列表
        """
        results = []
        messages = self._queue.copy()
        self._queue.clear()
        
        logger.info(f"开始发送队列中的 {len(messages)} 封邮件")
        
        for msg in messages:
            result = self.send_email(msg)
            results.append(result)
        
        success_count = sum(1 for r in results if r.success)
        logger.info(f"队列发送完成: 成功 {success_count}/{len(results)}")
        
        return results
