from __future__ import annotations

import logging
from datetime import date, timedelta
from pathlib import Path
from typing import Any

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.models.subscription import Subscription
from app.models.user import User
from app.services.email_service import EmailService

logger = logging.getLogger(__name__)

TEMPLATES_DIR = Path(__file__).resolve().parent.parent.parent / "templates"


class EmailScheduler:
    def __init__(self, email_service: EmailService | None = None):
        if email_service is None:
            from app.config import settings
            email_service = EmailService(
                simulate_mode=(settings.EMAIL_MODE == "mock"),
                smtp_host=settings.SMTP_HOST,
                smtp_port=settings.SMTP_PORT,
                smtp_user=settings.SMTP_USER,
                smtp_password=settings.SMTP_PASSWORD,
            )
        self.email_service = email_service

    def _load_template(self, template_name: str) -> str:
        template_path = TEMPLATES_DIR / template_name
        return template_path.read_text(encoding="utf-8")

    def _render_template(self, template_html: str, context: dict[str, Any]) -> str:
        result = template_html
        for key, value in context.items():
            result = result.replace("{{" + key + "}}", str(value))
        return result

    async def send_geo_weekly_report(self, db: AsyncSession) -> int:
        stmt = select(User).where(User.isActive == True)  # noqa: E712
        result = await db.execute(stmt)
        users = result.scalars().all()

        sent_count = 0
        template_html = self._load_template("geo_weekly_report.html")

        for user in users:
            try:
                context = {
                    "user_name": user.name or user.email,
                    "score_change": "+5",
                    "score_direction": "up",
                    "current_score": "78",
                    "previous_score": "73",
                    "top_improved": "内容质量 (+12%), AI引用率 (+8%)",
                    "top_declined": "品牌权威 (-3%)",
                    "suggestions": "建议增加技术白皮书内容以提升品牌权威度",
                    "report_link": "https://geo-platform.com/dashboard/monitoring",
                    "year": str(date.today().year),
                }
                body_html = self._render_template(template_html, context)
                msg = self.email_service.render_template(
                    "alert_notification",
                    user.email,
                    {
                        "alert_type": "GEO周报",
                        "brand_name": "全部品牌",
                        "severity": "info",
                        "description": "GEO周度变化报告",
                        "timestamp": date.today().isoformat(),
                    },
                )
                msg.body_html = body_html
                msg.subject = f"[GEO平台] GEO周报 - {date.today().isoformat()}"
                send_result = self.email_service.send_email(msg)
                if send_result.success:
                    sent_count += 1
            except Exception as e:
                logger.error(f"发送周报邮件失败: {user.email}, 错误: {e}")

        logger.info(f"GEO周报发送完成: {sent_count}/{len(users)}")
        return sent_count

    async def send_renewal_reminder(self, db: AsyncSession) -> int:
        today = date.today()
        thresholds = [7, 3, 1]
        sent_count = 0

        template_html = self._load_template("renewal_reminder.html")

        for days in thresholds:
            target_date = today + timedelta(days=days)
            stmt = select(Subscription).where(
                Subscription.status == "active",
                Subscription.end_date == target_date,
            )
            result = await db.execute(stmt)
            subscriptions = result.scalars().all()

            for sub in subscriptions:
                try:
                    user_stmt = select(User).where(User.id == sub.user_id)
                    user_result = await db.execute(user_stmt)
                    user = user_result.scalar_one_or_none()
                    if user is None:
                        continue

                    from app.services.subscription import PLANS
                    plan_data = PLANS.get(sub.plan, {})
                    plan_name = plan_data.get("name", sub.plan)
                    plan_price = plan_data.get("price", 0)

                    context = {
                        "user_name": user.name or user.email,
                        "plan_name": plan_name,
                        "end_date": sub.end_date.isoformat(),
                        "days_remaining": str(days),
                        "plan_price": str(plan_price),
                        "renew_link": "https://geo-platform.com/dashboard/subscription",
                        "year": str(today.year),
                    }
                    body_html = self._render_template(template_html, context)

                    msg = self.email_service.render_template(
                        "alert_notification",
                        user.email,
                        {
                            "alert_type": "续费提醒",
                            "brand_name": plan_name,
                            "severity": "warning",
                            "description": f"订阅将在{days}天后到期",
                            "timestamp": today.isoformat(),
                        },
                    )
                    msg.body_html = body_html
                    msg.subject = f"[GEO平台] 您的{plan_name}将在{days}天后到期"
                    send_result = self.email_service.send_email(msg)
                    if send_result.success:
                        sent_count += 1
                except Exception as e:
                    logger.error(f"发送续费提醒失败: {sub.user_id}, 错误: {e}")

        logger.info(f"续费提醒发送完成: {sent_count}")
        return sent_count

    async def send_trial_expiring_reminder(self, db: AsyncSession) -> int:
        today = date.today()
        target_date = today + timedelta(days=3)

        stmt = select(Subscription).where(
            Subscription.status == "active",
            Subscription.plan == "starter",
            Subscription.end_date == target_date,
        )
        result = await db.execute(stmt)
        subscriptions = result.scalars().all()

        sent_count = 0
        template_html = self._load_template("trial_expiring.html")

        for sub in subscriptions:
            try:
                user_stmt = select(User).where(User.id == sub.user_id)
                user_result = await db.execute(user_stmt)
                user = user_result.scalar_one_or_none()
                if user is None:
                    continue

                context = {
                    "user_name": user.name or user.email,
                    "days_remaining": "3",
                    "upgrade_link": "https://geo-platform.com/dashboard/subscription",
                    "year": str(today.year),
                }
                body_html = self._render_template(template_html, context)

                msg = self.email_service.render_template(
                    "alert_notification",
                    user.email,
                    {
                        "alert_type": "试用到期提醒",
                        "brand_name": "入门版",
                        "severity": "warning",
                        "description": "试用将在3天后到期",
                        "timestamp": today.isoformat(),
                    },
                )
                msg.body_html = body_html
                msg.subject = "[GEO平台] 您的试用将在3天后到期"
                send_result = self.email_service.send_email(msg)
                if send_result.success:
                    sent_count += 1
            except Exception as e:
                logger.error(f"发送试用到期提醒失败: {sub.user_id}, 错误: {e}")

        logger.info(f"试用到期提醒发送完成: {sent_count}")
        return sent_count

    async def send_welcome_email(self, user_email: str, user_name: str) -> bool:
        try:
            template_html = self._load_template("welcome.html")
            context = {
                "user_name": user_name or user_email,
                "dashboard_link": "https://geo-platform.com/dashboard",
                "diagnosis_link": "https://geo-platform.com/dashboard/diagnosis",
                "help_link": "https://geo-platform.com/help",
                "year": str(date.today().year),
            }
            body_html = self._render_template(template_html, context)

            msg = self.email_service.render_template(
                "alert_notification",
                user_email,
                {
                    "alert_type": "欢迎",
                    "brand_name": "GEO平台",
                    "severity": "info",
                    "description": "欢迎加入GEO平台",
                    "timestamp": date.today().isoformat(),
                },
            )
            msg.body_html = body_html
            msg.subject = "[GEO平台] 欢迎加入GEO平台"
            send_result = self.email_service.send_email(msg)
            return send_result.success
        except Exception as e:
            logger.error(f"发送欢迎邮件失败: {user_email}, 错误: {e}")
            return False
