"""审批通知推送 — 用户订阅的靶点有新批药时自动发邮件

架构（同 daily_digest.py）：
  notify_user()          → 单用户通知
  notify_all_subscribers() → 遍历所有订阅
  run_approval_notification() → ARQ 入口
"""

import logging
from datetime import datetime, timedelta, timezone

logger = logging.getLogger(__name__)

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

from app.config import settings
from app.db import async_session
from app.models.business import DrugApproval
from app.models.user import Tenant, User
from app.services.email_service import build_notification_email, send_email


SUBSCRIPTION_PREFIX = "approval_subs:"


async def notify_user(
    db: AsyncSession,
    user_id: str,
    user_email: str,
    user_name: str,
    target: str,
    approvals: list[dict],
) -> int:
    """为单个用户发送靶点审批通知邮件"""
    if not approvals:
        return 0

    # 构建邮件正文
    lines = [f"<p>您订阅的靶点 <strong>{target}</strong> 有以下新审批记录：</p>", "<ul>"]
    for a in approvals:
        lines.append(
            f"<li><strong>{a['drug_name']}</strong> ({a['generic_name']}) — "
            f"{a['indication'][:80]}{'…' if len(a['indication']) > 80 else ''} — "
            f"{a['approval_date']}</li>"
        )
    lines.append("</ul>")
    content = "\n".join(lines)

    html = build_notification_email(
        user_name=user_name,
        content=content,
        cta_text="查看全部审批",
        cta_link=f"{settings.PUBLIC_BASE_URL or ''}/drugs",
    )
    subject = f"🔔 靶点 {target} 有新审批 — {len(approvals)} 项"
    success = await send_email(user_email, subject, html)
    return len(approvals) if success else 0


async def notify_all_subscribers() -> dict:
    """遍历所有 tenant 的订阅，检查新增审批并通知"""
    stats = {"checked": 0, "sent": 0, "targets_with_new": 0, "errors": 0}
    cutoff = (datetime.now(timezone.utc) - timedelta(hours=24)).date()

    async with async_session() as db:
        # 1. 查近 24h 新增审批，按 target 分组
        result = await db.execute(
            select(DrugApproval)
            .where(DrugApproval.approval_date >= cutoff)
            .order_by(DrugApproval.target, DrugApproval.approval_date.desc())
        )
        new_approvals = result.scalars().all()

        if not new_approvals:
            logger.info("No new approvals in the last 24h, skipping notification")
            return stats

        # 按 target 分组
        by_target: dict[str, list[DrugApproval]] = {}
        for a in new_approvals:
            if a.target:
                by_target.setdefault(a.target, []).append(a)

        # 2. 遍历所有活跃的 tenant，查找订阅
        tenants = await db.execute(
            select(Tenant).where(Tenant.status == "active").limit(500)
        )
        for tenant in tenants.scalars().all():
            settings_dict = tenant.settings or {}
            for key, targets in settings_dict.items():
                if not key.startswith(SUBSCRIPTION_PREFIX):
                    continue
                if not isinstance(targets, list):
                    continue

                user_sub = key[len(SUBSCRIPTION_PREFIX):]
                try:
                    import uuid
                    user_uuid = uuid.UUID(user_sub)
                except (ValueError, TypeError):
                    continue

                # 找此用户订阅的靶点中有哪些有新审批
                matching_targets = {t for t in targets if t in by_target}
                if not matching_targets:
                    continue

                # 查用户信息
                user = await db.get(User, user_uuid)
                if not user or not user.is_active or not user.email:
                    continue

                for tgt in matching_targets:
                    count = await notify_user(
                        db, str(user.id), user.email, user.display_name,
                        tgt, [
                            {
                                "drug_name": a.drug_name,
                                "generic_name": a.generic_name,
                                "indication": a.indication,
                                "approval_date": str(a.approval_date),
                            }
                            for a in by_target[tgt]
                        ],
                    )
                    if count > 0:
                        stats["sent"] += 1
                stats["targets_with_new"] += len(matching_targets)
                stats["checked"] += 1

    logger.info(
        "Approval notification: %d users checked, %d sent, %d targets with new approvals",
        stats["checked"], stats["sent"], stats["targets_with_new"],
    )
    return stats


async def run_approval_notification() -> dict:
    """ARQ 定时任务入口"""
    stats = await notify_all_subscribers()
    logger.info(
        "Approval notification complete: %d sent, %d new targets",
        stats["sent"], stats["targets_with_new"],
    )
    return stats
