# retoor <retoor@molodetz.nl>
import argparse
import json
import time

HTML_PROVIDERS = ("brave", "ddg_html", "yahoo", "mojeek", "yandex")
RESERVE_PROVIDERS = ("bing",)
API_PROVIDERS = ("ddg_instant", "searxng", "qwant", "jina", "stackexchange", "wikipedia", "wikidata")
PAID_PROVIDERS = ("exa",)
CHAIN = HTML_PROVIDERS + API_PROVIDERS + RESERVE_PROVIDERS + PAID_PROVIDERS
ROUND_SECONDS = 60.0


def order_names(names, scores):
    return sorted(names, key=lambda name: scores.get(name, 0.5), reverse=True)


def run_chain(names, fetch, record, budget_seconds=ROUND_SECONDS, seen=None, reserve_after=2):
    seen = seen if seen is not None else set()
    merged, used, failures = [], [], []
    html_fails = 0
    deadline = time.monotonic() + budget_seconds
    for name in names:
        if name in RESERVE_PROVIDERS and html_fails < reserve_after:
            continue
        if name in PAID_PROVIDERS and merged:
            continue
        if time.monotonic() >= deadline:
            break
        started = time.monotonic()
        try:
            found = list(fetch(name) or [])
        except Exception as exc:
            record(name, False, time.monotonic() - started)
            failures.append({"provider": name, "error": str(exc)[:200]})
            if name in HTML_PROVIDERS:
                html_fails += 1
            continue
        elapsed = time.monotonic() - started
        record(name, bool(found), elapsed)
        if not found:
            failures.append({"provider": name, "error": "no results"})
            if name in HTML_PROVIDERS:
                html_fails += 1
            continue
        used.append(name)
        for row in found:
            url = (row.get("url") or "").strip()
            if not url or url in seen:
                continue
            seen.add(url)
            merged.append({"provider": name, "url": url, "title": row.get("title", "")[:200], "snippet": row.get("snippet", "")[:500]})
    return {"results": merged, "used": used, "failures": failures, "seen": sorted(seen)}


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Simulate one ordered provider round from a fixture file.")
    parser.add_argument("fixture", help="JSON file with results, scores, and optional stats maps")
    args = parser.parse_args()
    with open(args.fixture, encoding="utf-8") as handle:
        payload = json.load(handle)
    fixture = payload.get("results", {})
    names = order_names([name for name in CHAIN if name in fixture], payload.get("scores", {}))
    names += [name for name in fixture if name not in CHAIN]
    visits = []

    def replay(name):
        visits.append(name)
        return fixture[name]

    outcome = run_chain(names, replay, lambda name, ok, elapsed: None)
    outcome["call_order"] = visits
    print(json.dumps(outcome))
