"""Seed tags/journals and re-tag pipeline articles.

Usage: PYTHONPATH=. python scripts/seed_tags_only.py
"""
import os, sys, json
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))

os.environ.setdefault("DATABASE_URL", "postgresql+asyncpg://scilit:scilit_dev@localhost:5432/scilit")
os.environ.setdefault("JWT_SECRET", "dev-secret-change-in-production")
os.environ.setdefault("DEBUG", "true")
os.environ.setdefault("SPECIALTY", "oncology")

import asyncio, uuid
from sqlalchemy import select
from app.db import async_session
from app.models.literature import GlobalTag, GlobalJournal, GlobalLiterature, GlobalLiteratureTag


async def import_tags():
    with open(os.path.join(os.path.dirname(__file__), "seed_oncology_tags.json"), encoding="utf-8") as f:
        tags_data = json.load(f)
    tags_data.sort(key=lambda x: x["level"])
    path_to_id = {}
    count = 0
    async with async_session() as db:
        # 加载已存在的标签，按 mesh_ui 和 path 去重
        result = await db.execute(select(GlobalTag))
        existing_tags = result.scalars().all()
        existing_by_mesh = {t.mesh_ui for t in existing_tags if t.mesh_ui}
        existing_by_path = {t.path for t in existing_tags}
        # 加载已存在的标签到 path_to_id（用于 parent_id 解析）
        for t in existing_tags:
            path_to_id[t.path] = t.id

        for t in tags_data:
            # 跳过已存在的标签
            if t.get("mesh_ui") and t["mesh_ui"] in existing_by_mesh:
                path_to_id[t["path"]] = path_to_id.get(t["path"])
                continue
            if t["path"] in existing_by_path:
                continue

            parent_id = None
            if t.get("parent_path"):
                parent_id = path_to_id.get(t["parent_path"])
            tag = GlobalTag(
                id=uuid.uuid4(), name_zh=t["name_zh"], name_en=t.get("name_en"),
                path=t["path"], level=t["level"], parent_id=parent_id,
                tag_category=t["tag_category"], mesh_ui=t.get("mesh_ui"),
                is_selectable=(t["level"] == 2),
                is_active=True,
                source="manual",
            )
            db.add(tag)
            await db.flush()
            path_to_id[t["path"]] = tag.id
            existing_by_path.add(t["path"])
            if t.get("mesh_ui"):
                existing_by_mesh.add(t["mesh_ui"])
            count += 1
        await db.commit()
    print(f"  Tags imported: {count}")
    return path_to_id


async def import_journals():
    journals = [
        ("New England Journal of Medicine", "0028-4793", "1", 176.0),
        ("The Lancet", "0140-6736", "1", 98.4),
        ("JAMA", "0098-7484", "1", 63.1),
        ("BMJ", "0959-8138", "1", 93.6),
        ("Journal of Clinical Oncology", "0732-183X", "2", 42.1),
        ("Lancet Oncology", "1474-5488", "2", 51.0),
        ("JAMA Oncology", "2374-2437", "2", 28.7),
        ("Cancer Discovery", "2159-8290", "2", 29.5),
        ("Annals of Oncology", "0923-7534", "3", 48.0),
        ("Clinical Cancer Research", "1078-0432", "3", 11.5),
        ("Journal of the National Cancer Institute", "0027-8874", "3", 9.6),
        ("Cancer Cell", "1878-0261", "3", 48.8),
        ("European Journal of Cancer", "0959-8049", "3", 8.4),
        ("Cancer Research", "0008-5472", "3", 11.2),
        ("Nature Medicine", "1078-8956", "2", 82.9),
        ("Nature Cancer", "2662-1347", "3", 22.3),
        ("Cancer", "0008-543X", "4", 6.2),
        ("Blood", "0006-4971", "4", 21.0),
        ("Leukemia", "0887-6924", "4", 11.4),
        ("Int J Radiat Oncol Biol Phys", "0360-3016", "4", 7.0),
        ("Journal of the NCCN", "1540-1405", "4", 11.0),
        ("Journal of Thoracic Oncology", "1556-0864", "4", 12.5),
        ("Lung Cancer", "0169-5002", "4", 5.0),
    ]
    async with async_session() as db:
        for name, issn, tier, if_ in journals:
            db.add(GlobalJournal(id=uuid.uuid4(), name=name, issn=issn, tier=tier, impact_factor=if_, publisher="—"))
        await db.commit()
    print(f"  Journals imported: {len(journals)}")


async def retag_pipeline_articles():
    """Re-tag pipeline articles that have MeSH headings but no tag associations."""
    async with async_session() as db:
        # Fetch all articles with mesh_headings
        result = await db.execute(
            select(GlobalLiterature.id, GlobalLiterature.mesh_headings, GlobalLiterature.pmid)
            .where(GlobalLiterature.mesh_headings.isnot(None))
        )
        all_rows = result.all()
        # Filter non-empty mesh_headings in Python (JSONB comparison is tricky)
        rows = [(r.id, r.mesh_headings, r.pmid) for r in all_rows
                if r.mesh_headings and (isinstance(r.mesh_headings, list) and len(r.mesh_headings) > 0)]
        print(f"  Articles with MeSH headings: {len(rows)}")

        # Build mesh_ui → tag lookup
        tag_result = await db.execute(select(GlobalTag))
        all_tags = tag_result.scalars().all()
        mesh_to_tag = {t.mesh_ui: t for t in all_tags if t.mesh_ui}
        print(f"  Tags with mesh_ui: {len(mesh_to_tag)}")

        tagged_count = 0
        lit_tagged = 0
        for lit_id, mesh_headings, pmid in rows:
            mesh_heading_list = mesh_headings if isinstance(mesh_headings, list) else []
            matched_tags = []
            for mh in mesh_heading_list:
                ui = mh.get("ui") or mh.get("mesh_ui")
                if ui and ui in mesh_to_tag:
                    matched_tags.append((mesh_to_tag[ui], mh.get("major", False)))

            if not matched_tags:
                continue

            # Check existing tag associations
            existing_result = await db.execute(
                select(GlobalLiteratureTag.tag_id).where(
                    GlobalLiteratureTag.literature_id == lit_id,
                    GlobalLiteratureTag.tag_id.in_([t.id for t, _ in matched_tags]),
                )
            )
            existing_ids = {r for (r,) in existing_result.all()}

            added = 0
            for tag, is_major in matched_tags:
                if tag.id in existing_ids:
                    continue
                db.add(GlobalLiteratureTag(
                    literature_id=lit_id,
                    tag_id=tag.id,
                    is_major=is_major,
                ))
                added += 1

            if added:
                tagged_count += added
                lit_tagged += 1

        await db.commit()
        print(f"  Tagged: {lit_tagged} articles, {tagged_count} tag associations")


async def main():
    print("=== Step 1: Import tags ===")
    tag_map = await import_tags()

    print("\n=== Step 2: Import journals ===")
    try:
        await import_journals()
    except Exception as e:
        print(f"  Journals already exist or error: {e}")

    print("\n=== Step 3: Re-tag pipeline articles ===")
    await retag_pipeline_articles()

    # Verify
    async with async_session() as db:
        from sqlalchemy import func
        tc = await db.scalar(select(func.count(GlobalTag.id)))
        ltc = await db.scalar(select(func.count(GlobalLiteratureTag.id)))
        jc = await db.scalar(select(func.count(GlobalJournal.id)))
        print(f"\n=== Verification ===")
        print(f"  Total tags: {tc}")
        print(f"  Total tag associations: {ltc}")
        print(f"  Total journals: {jc}")


if __name__ == "__main__":
    asyncio.run(main())
