"""
Backfill missing years (2018-2023) via Europe PMC API.

Patches pubmed_api._YEAR_FILTER year-by-year and calls _run_pipeline
for each year. Europe PMC supports 5000 results/query with cursor pagination.

Usage:
    python scripts/backfill_missing_years.py [--years 2018-2023] [--broad-only] [--majr-only]
"""

import argparse
import asyncio
import logging
import sys

logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger("backfill")

# Broad oncology queries (mirrored from pubmed_api.py with _YEAR_FILTER)
_BROAD_QUERIES_TMPL = [
    '("lung cancer"[Title/Abstract] OR "lung carcinoma"[Title/Abstract] OR "lung adenocarcinoma"[Title/Abstract]) AND {year_filter}',
    '("breast cancer"[Title/Abstract] OR "breast carcinoma"[Title/Abstract]) AND {year_filter}',
    '("colorectal cancer"[Title/Abstract] OR "colon cancer"[Title/Abstract] OR "rectal cancer"[Title/Abstract]) AND {year_filter}',
    '("gastric cancer"[Title/Abstract] OR "stomach cancer"[Title/Abstract]) AND {year_filter}',
    '("hepatocellular"[Title/Abstract] OR "liver cancer"[Title/Abstract] OR "hepatic"[Title/Abstract]) AND {year_filter}',
    '("prostate cancer"[Title/Abstract] OR "prostatic cancer"[Title/Abstract]) AND {year_filter}',
    '("leukemia"[Title/Abstract] OR "leukaemia"[Title/Abstract]) AND {year_filter}',
    '("lymphoma"[Title/Abstract] OR "Hodgkin"[Title/Abstract] OR "non-Hodgkin"[Title/Abstract]) AND {year_filter}',
    '("melanoma"[Title/Abstract]) AND {year_filter}',
    '("pancreatic cancer"[Title/Abstract]) AND {year_filter}',
    '("ovarian cancer"[Title/Abstract] OR "ovarian carcinoma"[Title/Abstract]) AND {year_filter}',
    '("esophageal cancer"[Title/Abstract] OR "oesophageal"[Title/Abstract]) AND {year_filter}',
    '("glioma"[Title/Abstract] OR "glioblastoma"[Title/Abstract]) AND {year_filter}',
    '("head and neck cancer"[Title/Abstract] OR "oral cancer"[Title/Abstract] OR "squamous cell carcinoma"[Title/Abstract]) AND {year_filter}',
    '("sarcoma"[Title/Abstract] OR "osteosarcoma"[Title/Abstract]) AND {year_filter}',
]


def _build_broad_queries(year_filter):
    return [t.replace("{year_filter}", year_filter) for t in _BROAD_QUERIES_TMPL]


async def run_for_year(year, broad_only, majr_only, max_per_query, no_oa):
    import app.services.pubmed_api as pubmed_api

    if no_oa:
        async def _no_op(db, pending): return 0
        pubmed_api._fetch_oa_fulltexts = _no_op

    year_filter = "{year}:{year}[dp]".format(year=year)
    logger.info("== Backfilling %d (filter=%s) ==", year, year_filter)

    # Patch module-level variables
    pubmed_api._YEAR_FILTER = year_filter
    pubmed_api.EUROPE_PMC_SEARCH_URL = "https://www.ebi.ac.uk/europepmc/webservices/rest/search"

    # Rebuild BROAD_ONCOLOGY_QUERIES with the patched year
    pubmed_api.BROAD_ONCOLOGY_QUERIES = _build_broad_queries(year_filter)

    from app.db import async_session

    stats_accum = {"searched": 0, "fetched": 0, "new": 0, "updated": 0,
                   "tagged": 0, "feeds": 0, "citations": 0, "oa_fetched": 0}

    async with async_session() as db:
        if not broad_only:
            logger.info("-- MAJR mode --")
            try:
                s = await pubmed_api._run_pipeline(
                    db=db,
                    max_per_query=max_per_query,
                    use_majr=True,
                    use_broad=False,
                    precision_mode="majr",
                    update_citations=False,
                    use_europe_pmc=True,
                )
                logger.info("MAJR %d: %s", year, s)
                for k in stats_accum:
                    stats_accum[k] += s.get(k, 0)
            except Exception as e:
                logger.error("MAJR %d FAILED: %s", year, e, exc_info=True)

        if not majr_only:
            logger.info("-- Broad mode --")
            try:
                s = await pubmed_api._run_pipeline(
                    db=db,
                    max_per_query=max_per_query,
                    use_majr=False,
                    use_broad=True,
                    precision_mode="majr",
                    update_citations=False,
                    use_europe_pmc=True,
                )
                logger.info("Broad %d: %s", year, s)
                for k in stats_accum:
                    stats_accum[k] += s.get(k, 0)
            except Exception as e:
                logger.error("Broad %d FAILED: %s", year, e, exc_info=True)

    logger.info("Year %d done: searched=%d fetched=%d new=%d updated=%d",
                year, stats_accum.get("searched", 0), stats_accum.get("fetched", 0),
                stats_accum.get("new", 0), stats_accum.get("updated", 0))
    return stats_accum


async def main():
    parser = argparse.ArgumentParser(description="Backfill missing years via Europe PMC")
    parser.add_argument("--years", type=str, default="2018-2023",
                        help="Year range, e.g. '2018-2023' or '2018,2019,2020'")
    parser.add_argument("--broad-only", action="store_true")
    parser.add_argument("--majr-only", action="store_true")
    parser.add_argument("--max-per-query", type=int, default=5000)
    parser.add_argument("--no-oa", action="store_true", help="Skip OA fulltext fetching (much faster)")
    args = parser.parse_args()

    years = []
    if "-" in args.years:
        parts = args.years.split("-")
        years = list(range(int(parts[0]), int(parts[1]) + 1))
    elif "," in args.years:
        years = [int(y) for y in args.years.split(",")]
    else:
        years = [int(args.years)]

    sys.path.insert(0, "/app")
    import app.services.pubmed_api  # noqa: trigger app bootstrap

    total = {"searched": 0, "fetched": 0, "new": 0, "updated": 0,
             "tagged": 0, "feeds": 0, "citations": 0, "oa_fetched": 0}

    for year in years:
        s = await run_for_year(year, args.broad_only, args.majr_only, args.max_per_query, args.no_oa)
        for k in total:
            total[k] += s.get(k, 0)
        await asyncio.sleep(3)

    logger.info("== ALL DONE ==")
    logger.info("Total: searched=%d fetched=%d new=%d updated=%d",
                total.get("searched", 0), total.get("fetched", 0),
                total.get("new", 0), total.get("updated", 0))


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