"""热搜缓存服务：定时预计算热门文献并缓存"""

import logging
from datetime import datetime, timedelta

from sqlalchemy import and_, func, select

from app.compat import UTC
from app.core.cache import cache
from app.db import async_session
from app.models.literature import GlobalLiterature
from app.schemas.literature import cap_pub_date
from app.services.tag_loader import load_tags_for_literature

logger = logging.getLogger(__name__)

CACHE_KEY = "hot_articles"
CACHE_TTL = 1800  # 30 minutes
HOT_LIMIT = 30  # 缓存前 30 条（支持 3 页 × 10 条/页）


def _build_cards(items, tags_map: dict[str, list]) -> list[dict]:
    """将 GlobalLiterature 转为 API 返回格式"""
    cards = []
    for lit in items:
        authors = lit.authors or []
        first_author = authors[0].get("family", "") if authors else ""
        tlist = tags_map.get(str(lit.id), [])
        enriched_tags = []
        for t in tlist:
            tag = dict(t)
            if "::" in tag.get("path", ""):
                tag["name_zh"] = tag["path"].split("::")[-1]
            enriched_tags.append(tag)
        cards.append({
            "id": str(lit.id),
            "pmid": lit.pmid,
            "title": lit.title,
            "journal": lit.journal,
            "pub_date": cap_pub_date(lit.pub_date),
            "article_date": lit.article_date.isoformat() if lit.article_date else None,
            "cited_by_count": lit.cited_by_count or 0,
            "first_author": first_author,
            "tags": enriched_tags,
        })
    return cards


async def precompute_hot_articles():
    """预计算热门文献并写入缓存（定时任务调用）"""
    year_ago = datetime.now(UTC) - timedelta(days=365)

    async with async_session() as db:
        q = (
            select(GlobalLiterature)
            .where(and_(GlobalLiterature.pub_date >= year_ago, GlobalLiterature.cited_by_count > 0))
            .order_by(GlobalLiterature.cited_by_count.desc().nullslast(), GlobalLiterature.pub_date.desc().nullslast())
            .limit(HOT_LIMIT)
        )
        result = await db.execute(q)
        items = result.scalars().all()

        if not items:
            logger.warning("热搜预计算：未找到有被引次数的文献")
            return

        ids = [str(lit.id) for lit in items]
        tm = await load_tags_for_literature(db, ids)
        cards = _build_cards(items, tm)

        await cache.set(CACHE_KEY, {"items": cards}, ttl=CACHE_TTL)
        logger.info("热搜缓存已更新：%d 条文献", len(cards))
