"""首页 Feed 缓存服务：定时预计算最新文献并缓存"""

import logging

from sqlalchemy import select

from app.core.cache import cache
from app.db import async_session
from app.models.literature import GlobalJournal, 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 = "homepage:feed"
CACHE_TTL = 1800  # 30 分钟
PRECOMPUTE_LIMIT = 50  # 预计算 50 条（支持 2 页 × 20 条 + 缓冲）


def _get_affiliation(authors: list) -> str | None:
    """取第一个有机构的作者信息，缩写机构名"""
    if not authors:
        return None
    for a in authors:
        aff = a.get("affiliation", "") or ""
        if aff.strip():
            short = aff.split(",")[0].strip()
            return short[:30] + ("..." if len(short) > 30 else "")
    return None


def _build_cards(items, tier_map: dict[str, str], name_map: dict[str, str] | None = None,
                 tags_map: dict[str, list] | None = None) -> list[dict]:
    """将 GlobalLiterature 转为首页卡片格式"""
    cards = []
    for lit in items:
        authors = lit.authors or []
        first_author = authors[0].get("family", "") if authors else ""
        affiliation = _get_affiliation(authors)
        tlist = (tags_map or {}).get(str(lit.id), [])
        ai = lit.ai_summary.get("one_liner") if lit.ai_summary and isinstance(lit.ai_summary, dict) else None
        journal = (name_map or {}).get(lit.journal_issn) or lit.journal
        cards.append({
            "id": str(lit.id),
            "pmid": lit.pmid,
            "title": lit.title,
            "first_author": first_author,
            "affiliation": affiliation,
            "journal": journal,
            "journal_issn": lit.journal_issn,
            "journal_tier": tier_map.get(lit.journal_issn),
            "pub_date": cap_pub_date(lit.pub_date),
            "article_date": lit.article_date.isoformat() if lit.article_date else None,
            "pub_year": lit.pub_year,
            "doi": lit.doi,
            "pmc_id": lit.pmc_id,
            "is_oa": lit.is_oa,
            "cited_by_count": lit.cited_by_count or 0,
            "pub_types": lit.pub_types,
            "retracted": lit.retracted,
            "is_negative_result": lit.is_negative_result,
            "tags": tlist,
            "ai_summary": ai,
            "created_at": lit.created_at.isoformat() if lit.created_at else None,
            "updated_at": lit.updated_at.isoformat() if lit.updated_at else None,
        })
    return cards


async def precompute_homepage_feed():
    """预计算首页 Feed 并写入缓存"""
    async with async_session() as db:
        q = (
            select(
                GlobalLiterature.id,
                GlobalLiterature.pmid,
                GlobalLiterature.title,
                GlobalLiterature.authors,
                GlobalLiterature.journal,
                GlobalLiterature.journal_issn,
                GlobalLiterature.pub_date,
                GlobalLiterature.pub_year,
                GlobalLiterature.doi,
                GlobalLiterature.pmc_id,
                GlobalLiterature.is_oa,
                GlobalLiterature.cited_by_count,
                GlobalLiterature.pub_types,
                GlobalLiterature.article_date,
                GlobalLiterature.ai_summary,
                GlobalLiterature.retracted,
                GlobalLiterature.is_negative_result,
                GlobalLiterature.created_at,
                GlobalLiterature.updated_at,
            )
            .order_by(GlobalLiterature.pub_date.desc().nullslast())
            .limit(PRECOMPUTE_LIMIT)
        )
        result = await db.execute(q)
        items = result.all()

        if not items:
            logger.warning("首页缓存预计算：未找到文献")
            return

        # Batch load tags
        lit_ids = [str(lit.id) for lit in items]
        tags_map = await load_tags_for_literature(db, lit_ids)

        # Batch load journal tiers + canonical names
        tier_map = {}
        name_map = {}
        issns = list(set(lit.journal_issn for lit in items if lit.journal_issn))
        if issns:
            jr = await db.execute(
                select(GlobalJournal.issn, GlobalJournal.tier, GlobalJournal.name).where(GlobalJournal.issn.in_(issns))
            )
            for issn_, tier_, name_ in jr.all():
                tier_map[issn_] = tier_
                name_map[issn_] = name_

        cards = _build_cards(items, tier_map, name_map, tags_map)
        await cache.set(CACHE_KEY, {"items": cards}, ttl=CACHE_TTL)
        logger.info("首页缓存已更新：%d 条文献，%d 含标签", len(cards), sum(1 for c in cards if c.get("tags")))
