#!/usr/bin/env python3
"""Collect source material for one themed episode day, written as JSON.

The material file is the single source both script writers (local gemma and
claude -p) work from, so a bakeoff between writers compares WRITING, not
collection luck.

  thu — Native/Indigenous language-tech & data-sovereignty news (web search)
  fri — GeoAI: one arXiv paper picked + full text, plus general-AI zeitgeist news
  sat — week in review: everything kept in the last 7 days

Every day also gets 'radar': the most recent kept feed items for the daily
briefing segment. Web search runs through `claude -p` with WebSearch (no Tavily
key on this box); the results are saved so both writers see identical items.

Usage: collect_day.py --day thu|fri|sat --out material.json
"""
import argparse, json, os, re, subprocess, sys
from datetime import datetime, timezone, timedelta

HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.dirname(HERE)
sys.path.insert(0, HERE)
sys.path.insert(0, ROOT)
from build_feed import fetch_arxiv, LLM_URL, LLM  # noqa: E402
from paper_of_day import fetch_paper_text, llm    # noqa: E402

CLAUDE_MODEL = "claude-sonnet-5"

GEOAI_QUERY = ('(cat:cs.CV OR cat:cs.LG OR cat:eess.IV) AND '
               '(all:"remote sensing" OR all:"satellite imagery" OR all:"earth observation")')
GEOAI_STATEMENT = """I apply AI to geospatial data as a practitioner: I build
visualizations and tools with Sentinel-2 and other satellite imagery. Relevant:
earth-observation foundation models, ML on satellite imagery (segmentation,
detection, change detection, super-resolution), terrain and climate modeling,
geospatial ML tooling and benchmarks. Not relevant: pure GIS software without ML,
sensor-physics papers, single-crop agronomy studies with off-the-shelf methods."""


def claude_web_items(instruction, n_items):
    """One claude -p call with WebSearch; returns a list of item dicts."""
    prompt = (f"{instruction}\n\n"
              f"Use web search. Return ONLY a JSON array of at most {n_items} objects, "
              'each {"title": str, "url": str, "summary": "2-4 sentences, factual", '
              '"published": "YYYY-MM-DD or null"}. No prose before or after the JSON. '
              "Only include items you actually found sources for — never invent items.")
    for _ in range(2):
        r = subprocess.run(
            ["claude", "-p", "--model", CLAUDE_MODEL, "--allowedTools", "WebSearch,WebFetch"],
            input=prompt, capture_output=True, text=True, timeout=900)
        m = re.search(r"\[.*\]", r.stdout, re.S)
        if m:
            try:
                return json.loads(m.group(0))
            except json.JSONDecodeError:
                continue
    print(f"[collect] web search returned no parseable JSON:\n{r.stdout[:500]}", file=sys.stderr)
    return []


def recent_history(days):
    hist = json.load(open(os.path.join(ROOT, "history.json")))
    cutoff = (datetime.now(timezone.utc) - timedelta(days=days)).isoformat()
    return [h for h in hist if h["published"] >= cutoff]


def pick_geoai_paper():
    """arXiv search -> gemma picks the best fit -> full text fetched."""
    cands = fetch_arxiv(GEOAI_QUERY)[:25]
    listing = "\n".join(f"[{i}] {c['title']} — {c['summary'][:200]}" for i, c in enumerate(cands))
    raw = llm(f"RESEARCH STATEMENT:\n{GEOAI_STATEMENT}\n\nPAPERS:\n{listing}\n\n"
              "Which ONE paper is most worth a deep-dive for this practitioner? "
              'Reply ONLY with JSON: {"index": <int>, "reason": "<one sentence>"}',
              max_tokens=120)
    d = json.loads(re.search(r"\{.*\}", raw, re.S).group(0))
    order = [int(d["index"])] if 0 <= int(d["index"]) < len(cands) else []
    order += [i for i in range(len(cands)) if i not in order]
    for i in order[:5]:                      # picked first, then fall through
        text = fetch_paper_text(cands[i]["id"])
        if text:
            return {"paper": cands[i], "reason": d.get("reason", ""), "text": text}
    raise RuntimeError("no GeoAI paper with fetchable full text")


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--day", required=True, choices=["thu", "fri", "sat"])
    ap.add_argument("--out", required=True)
    args = ap.parse_args()

    mat = {"day": args.day,
           "date": datetime.now(timezone.utc).strftime("%Y-%m-%d"),
           "radar": recent_history(3)}

    if args.day == "thu":
        mat["news"] = claude_web_items(
            "Find this past week's news on: Indigenous or tribal language technology "
            "(apps, models, programs); Indigenous data sovereignty and AI data governance; "
            "language revitalization efforts using technology (Maori, Cherokee, Hawaiian, "
            "Navajo, Ojibwe, and other nations worldwide).", 10)
    elif args.day == "fri":
        mat["geoai"] = pick_geoai_paper()
        mat["zeitgeist"] = claude_web_items(
            "Find the most significant general AI developments of the past week: major "
            "model releases, important research results, notable industry or policy moves. "
            "Significance over volume — the handful of things a busy practitioner must know.", 8)
    elif args.day == "sat":
        mat["week"] = recent_history(7)
        metas = []
        epdir = os.path.join(HERE, "episodes")
        week_ago = datetime.now(timezone.utc) - timedelta(days=7)
        for f in sorted(os.listdir(epdir)):
            if f.endswith(".json"):
                p = os.path.join(epdir, f)
                if datetime.fromtimestamp(os.path.getmtime(p), tz=timezone.utc) >= week_ago:
                    metas.append(json.load(open(p)).get("title", f))
        mat["episodes_this_week"] = metas

    tmp = args.out + ".tmp"
    json.dump(mat, open(tmp, "w"), indent=1)
    os.replace(tmp, args.out)
    sizes = {k: (len(v) if isinstance(v, list) else "1 paper") for k, v in mat.items()
             if k in ("radar", "news", "zeitgeist", "week", "geoai")}
    print(f"[collect] {args.day}: {sizes} -> {args.out}")


if __name__ == "__main__":
    main()
