#!/usr/bin/env python3
"""Fetch top-5 reaction terms per drug from the openFDA drug event API.

Saves every raw response (verbatim bytes) keyed by drug name into raw.json
BEFORE any analysis. Requests are spaced 0.4s apart and capped at 40.
"""

import json
import time
import urllib.error
import urllib.parse
import urllib.request
from datetime import datetime, timezone

OUT = "/Volumes/Storage/DeepSeek/workspace/pgx-gap-map/research-notes/faers-adverse-events"
ENDPOINT = "https://api.fda.gov/drug/event.json"
UA = "research-notes/1.0 (public-data analysis; python-urllib)"
SLEEP = 0.4
CAP = 40
LIMIT = 5

DRUGS = [
    "atorvastatin",
    "metformin",
    "amoxicillin",
    "ibuprofen",
    "warfarin",
    "insulin glargine",
    "levothyroxine",
    "omeprazole",
    "sertraline",
    "allopurinol",
]

raw = {
    "_meta": {
        "fetched_utc": datetime.now(timezone.utc).isoformat(),
        "endpoint": ENDPOINT,
        "count_field": "patient.reaction.reactionmeddrapt.exact",
        "limit": LIMIT,
        "sleep_seconds": SLEEP,
        "request_cap": CAP,
        "user_agent": UA,
        "requests_attempted": 0,
        "failures": [],
    }
}

for drug in DRUGS:
    if raw["_meta"]["requests_attempted"] >= CAP:
        raw["_meta"]["failures"].append(
            {"drug": drug, "status": "skipped", "reason": f"request cap {CAP} reached"}
        )
        continue

    search = f'patient.drug.medicinalproduct:"{drug}"'
    qs = urllib.parse.urlencode(
        {
            "search": search,
            "count": "patient.reaction.reactionmeddrapt.exact",
            "limit": LIMIT,
        }
    )
    url = f"{ENDPOINT}?{qs}"
    req = urllib.request.Request(url, headers={"User-Agent": UA, "Accept": "application/json"})
    raw["_meta"]["requests_attempted"] += 1

    try:
        with urllib.request.urlopen(req, timeout=60) as resp:
            body = resp.read()
            status = resp.status
        text = body.decode("utf-8")
        parsed = json.loads(text)
        raw[drug] = {
            "url": url,
            "http_status": status,
            "response_json": parsed,
        }
        n = len(parsed.get("results", [])) if isinstance(parsed, dict) else 0
        print(f"{drug:<18} HTTP {status}  results={n}")
    except urllib.error.HTTPError as e:
        body = e.read().decode("utf-8", "replace")
        raw[drug] = {"url": url, "http_status": e.code, "error_body": body}
        raw["_meta"]["failures"].append(
            {"drug": drug, "status": "http_error", "code": e.code,
             "reason": body[:300], "url": url}
        )
        print(f"{drug:<18} HTTP {e.code}  FAILED")
    except Exception as e:  # noqa: BLE001
        raw[drug] = {"url": url, "http_status": None, "error_body": repr(e)}
        raw["_meta"]["failures"].append(
            {"drug": drug, "status": "exception", "reason": repr(e), "url": url}
        )
        print(f"{drug:<18} EXCEPTION  {e!r}")

    time.sleep(SLEEP)

path = f"{OUT}/raw.json"
with open(path, "w", encoding="utf-8") as f:
    json.dump(raw, f, indent=2, ensure_ascii=False)

print("\n--- saved", path)
print("requests attempted:", raw["_meta"]["requests_attempted"])
print("failures:", len(raw["_meta"]["failures"]))
for fa in raw["_meta"]["failures"]:
    print("  ", fa)
