"""Verify every DOI in a CSV column resolves at Crossref and report title mismatches.
usage: python3 scripts/check_citations.py <csv> <column>
A cell may hold several sources separated by ' ; '. Non-DOI URLs are HEAD-checked."""
import csv, json, re, sys, time, urllib.request, urllib.parse
path, col = sys.argv[1], sys.argv[2]
seen = {}
def crossref(doi):
    try:
        d = json.load(urllib.request.urlopen(urllib.request.Request("https://api.crossref.org/works/" + urllib.parse.quote(doi),
            headers={"User-Agent": "pm-forecast (mailto:none)"}), timeout=30))
        return "ok", (d["message"].get("title") or [""])[0], (d["message"].get("issued", {}).get("date-parts") or [[None]])[0][0]
    except urllib.error.HTTPError as e:
        return f"HTTP {e.code}", "", None
    except Exception as e:
        return f"error {e}", "", None
def head(url):
    try:
        r = urllib.request.urlopen(urllib.request.Request(url, method="GET", headers={"User-Agent": "Mozilla/5.0"}), timeout=30)
        return f"HTTP {r.status}"
    except urllib.error.HTTPError as e:
        return f"HTTP {e.code}"
    except Exception as e:
        return f"error {e}"
bad = 0; n = 0
for r in csv.DictReader(open(path, newline="")):
    for part in [p.strip() for p in (r.get(col) or "").split(" ; ") if p.strip()]:
        m = re.search(r"10\.\d{4,9}/\S+", part)
        if m:
            doi = m.group(0).rstrip(".,;")
            while doi.endswith(")") and doi.count(")") > doi.count("("):
                doi = doi[:-1]  # drop a closing paren that belongs to the prose, keep balanced ones
        key = doi if m else (re.search(r"https?://\S+", part) or [None])[0] if re.search(r"https?://\S+", part) else None
        if not key:
            continue
        n += 1
        if key not in seen:
            seen[key] = crossref(key) if m else (head(key), "", None); time.sleep(1.0)
        st = seen[key][0]
        if not (st == "ok" or st.startswith("HTTP 2") or st.startswith("HTTP 3")):
            bad += 1; print(r.get("claim_id") or r.get("family"), key, st)
print(f"{n} citations checked, {len(seen)} unique, {bad} failed")
json.dump({k: v for k, v in seen.items()}, open(path + ".citecheck.json", "w"), indent=0)
