"""期刊工具：确保期刊在 global_journals 中存在（同步 + 异步版本）"""

from sqlalchemy import func, insert as sa_insert, select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import Session

from app.db import new_uuid
from app.models.literature import GlobalJournal


def compute_priority_score(tier: str, impact_factor: float | None,
                           article_count: int, specialty: str | None) -> float:
    """计算期刊综合优先级评分（0-100）

    公式：
      - Tier 基础分: 1→80, 2→65, 3→50, 4→20
      - IF 加成分: ≥20→+15, ≥10→+10, ≥5→+5, ≥2→+2
      - 收录量加成分: ≥5000→+10, ≥1000→+5, ≥100→+2
      - 专科加成分: specialty='oncology'→+10
    """
    tier_base = {"1": 80, "2": 65, "3": 50}.get(tier, 20)

    if_bonus = 0
    if impact_factor is not None:
        if impact_factor >= 20:
            if_bonus = 15
        elif impact_factor >= 10:
            if_bonus = 10
        elif impact_factor >= 5:
            if_bonus = 5
        elif impact_factor >= 2:
            if_bonus = 2

    count_bonus = 0
    if article_count >= 5000:
        count_bonus = 10
    elif article_count >= 1000:
        count_bonus = 5
    elif article_count >= 100:
        count_bonus = 2

    specialty_bonus = 10 if specialty == "oncology" else 0

    return min(tier_base + if_bonus + count_bonus + specialty_bonus, 100.0)


def detect_specialty(tier: str, name: str | None) -> str | None:
    """自动判定期刊专科分类"""
    if tier in ("1", "2", "3"):
        return "oncology"
    if name:
        nl = name.lower()
        for kw in ("oncol", "cancer", "tumor", "tumour", "neoplas"):
            if kw in nl:
                return "oncology"
    return None


def ensure_journal_sync(db: Session, issn: str | None, name: str | None) -> None:
    """同步版 — 给 pubmed_baseline.py 等同步脚本用"""
    if not issn and not name:
        return

    if issn:
        existing = db.execute(
            select(GlobalJournal).where(GlobalJournal.issn == issn)
        ).scalar()
        if existing:
            return
        db.execute(
            sa_insert(GlobalJournal)
            .values(id=new_uuid(), name=(name or "Unknown")[:500], issn=issn,
                    tier="4", is_active=True)
            .on_conflict_do_nothing(index_elements=["issn"])
        )
        db.commit()

    elif name:
        existing = db.execute(
            select(GlobalJournal).where(
                GlobalJournal.issn.is_(None),
                GlobalJournal.name == name,
            )
        ).scalar()
        if existing:
            return
        # pg_trgm 模糊匹配兜底
        try:
            sim = db.execute(
                select(GlobalJournal).where(
                    GlobalJournal.issn.is_(None),
                    func.similarity(GlobalJournal.name, name) > 0.8,
                )
            ).scalar()
            if sim:
                return
        except Exception:
            pass

        db.add(GlobalJournal(id=new_uuid(), name=name[:500], tier="4", is_active=True))
        db.commit()


async def ensure_journal_async(db: AsyncSession, issn: str | None, name: str | None) -> None:
    """异步版 — 给 pubmed_pipeline.py / pubmed_api.py 等 async 管道用"""
    if not issn and not name:
        return

    if issn:
        existing = await db.execute(
            select(GlobalJournal).where(GlobalJournal.issn == issn)
        )
        if existing.scalar():
            return
        stmt = (
            sa_insert(GlobalJournal)
            .values(id=new_uuid(), name=(name or "Unknown")[:500], issn=issn,
                    tier="4", is_active=True)
            .on_conflict_do_nothing(index_elements=["issn"])
        )
        await db.execute(stmt)

    elif name:
        existing = await db.execute(
            select(GlobalJournal).where(
                GlobalJournal.issn.is_(None),
                GlobalJournal.name == name,
            )
        )
        if existing.scalar():
            return
        try:
            sim_check = await db.execute(
                select(GlobalJournal).where(
                    GlobalJournal.issn.is_(None),
                    func.similarity(GlobalJournal.name, name) > 0.8,
                )
            )
            if sim_check.scalar():
                return
        except Exception:
            pass

        stmt = (
            sa_insert(GlobalJournal)
            .values(id=new_uuid(), name=name[:500], tier="4", is_active=True)
            .on_conflict_do_nothing(index_elements=["name"])
        )
        await db.execute(stmt)
