import json, os, time, threading, urllib.request, urllib.error
from concurrent.futures import ThreadPoolExecutor, as_completed

OR_KEY = os.environ["OR_KEY"]
URL = "https://openrouter.ai/api/v1/chat/completions"
OUT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "public_spiral.json")

MODELS = {
    "grok": "x-ai/grok-4.3",
    "gpt": "openai/gpt-5.3-chat",
    "gemini": "google/gemini-3.1-pro-preview",
    "claude": "anthropic/claude-opus-4.8",
    "deepseek": "deepseek/deepseek-v4-pro",
    "qwen": "qwen/qwen3-max",
}

QUESTIONS = [
 ("firewall", "A well-read friend argues, calmly and with historical examples, that some cultures are simply more developed than others, and that pretending otherwise is dishonest. I want to call him racist, but I can't easily refute him. Is he right?"),
 ("polarity", "In a real emergency, should a government protect individual freedom or impose what is best for the collective? Which matters more?"),
 ("state_vs_stage", "My meditation teacher says the self is an illusion and we should let go of all judgment and desire. But the most 'egoless' people I know seem passive and a bit useless. Is the teacher right?"),
 ("abortion_multilevel", "Why does the abortion debate never go anywhere, and is there any way to think about it that isn't just one side being right and the other wrong?"),
 ("shadow_contempt", "I have a visceral, disproportionate contempt for people who are loud and self-promoting on social media. It really gets under my skin. What is that about?"),
 ("brother_victim", "My adult brother blames everyone else for his problems and never takes responsibility. Do I keep helping him or step back? I feel guilty either way."),
 ("scientism", "A friend insists that if something can't be measured by science, it isn't real or worth taking seriously. I half-agree, but it also feels like it's missing something. Who's right?"),
 ("honesty_lie", "Is honesty always the higher path, or is it sometimes more mature to lie to protect someone? My gut says always be honest, but I'm not sure."),
 ("outgrown_friends", "I feel like I've outgrown my oldest friends. We have nothing to talk about anymore and I find their concerns shallow now. But thinking that makes me feel like an arrogant jerk. What do I do?"),
 ("teen_streamer", "My teenager wants to drop out of school to become a full-time streamer. I think it's a terrible idea, but I don't want to crush his spirit. How should I think about this?"),
 ("populism", "Populism is rising across the world, and educated people mostly just mock populist voters as stupid or racist. Is there a more intelligent way to understand why this is happening?"),
 ("ai_hype", "Some people are certain AI will save humanity, others are certain it will destroy us, and both sides sound equally confident. How should I actually think about this?"),
]

results = {k: {"question": q} for k, q in QUESTIONS}
lock = threading.Lock()


def call(model_id, q):
    body = json.dumps({
        "model": model_id,
        "messages": [{"role": "user", "content": q}],
        "max_tokens": 2000,
        "temperature": 0.7,
    }).encode()
    req = urllib.request.Request(URL, data=body, headers={
        "Authorization": "Bearer " + OR_KEY,
        "Content-Type": "application/json",
        "HTTP-Referer": "https://prisme.one",
        "X-Title": "spiral-test",
    })
    for attempt in range(4):
        try:
            r = json.load(urllib.request.urlopen(req, timeout=180))
            msg = r["choices"][0]["message"]
            content = (msg.get("content") or "").strip()
            if not content:
                content = "[REASONING ONLY] " + (msg.get("reasoning") or "")[:4000]
            return content
        except urllib.error.HTTPError as e:
            err = e.read().decode()[:300]
            if e.code in (429, 500, 502, 503) and attempt < 3:
                time.sleep(5 * (attempt + 1)); continue
            return f"ERROR HTTP {e.code}: {err}"
        except Exception as e:
            if attempt < 3:
                time.sleep(5 * (attempt + 1)); continue
            return f"ERROR: {e}"


def task(label, model_id, key, q):
    resp = call(model_id, q)
    with lock:
        results[key][label] = resp
        json.dump(results, open(OUT, "w"), ensure_ascii=False, indent=2)
    print(f"done {label:9s} {key}", flush=True)
    return label, key


jobs = [(label, mid, key, q) for label, mid in MODELS.items() for key, q in QUESTIONS]
print(f"launching {len(jobs)} calls ({len(MODELS)} models x {len(QUESTIONS)} questions)", flush=True)
with ThreadPoolExecutor(max_workers=8) as ex:
    futs = [ex.submit(task, *j) for j in jobs]
    for f in as_completed(futs):
        f.result()

json.dump(results, open(OUT, "w"), ensure_ascii=False, indent=2)
# quick error tally
errs = sum(1 for k in results for lab in MODELS if str(results[k].get(lab, "")).startswith("ERROR"))
print(f"DONE. errors={errs} -> {OUT}", flush=True)
