"""Open answer-quality benchmark - the run (C4).

Asks every question of a question set to the live demo assistant, exactly as the
website widget does, and saves the raw responses unchanged. Scoring is a separate
step (score.py) so anyone can re-score the published raw answers without re-running.

    python tools/eval-benchmark/run.py Documents/c4-benchmark/questions-med.json OUT/raw-med.jsonl
    python tools/eval-benchmark/run.py QUESTIONS OUT [--only med-he] [--delay 2.5]

The API keys below are the public widget keys printed in each demo page's <script>
tag; they only allow questions. Every request carries visitorId "qa-smoke-eval-...",
which the platform treats as a synthetic probe: the answer is generated and logged
as for a visitor, but no lead, handoff or notification reaches a person.
"""
import argparse, datetime, json, sys, time, urllib.error, urllib.request

sys.stdout.reconfigure(encoding='utf-8')
API = 'https://api.slatech.ai/v1/query'
SITES = {
    'med': {'key': '030ee3d6e39d43d6b83b6e4a2c319acce6b175526e2942f4bfdd52970e93e3f7',
            'page': 'https://med.slatech.ai/demo/clinic/{lang}/'},
    'biz': {'key': '6a2e4db8f5cf46dc89183d433bf51496e61663993e874342b24b0f6e6cc64ede',
            'page': 'https://business.slatech.ai/demo/office/{lang}/'},
}


def ask(site, item):
    body = {'question': item['question'], 'pageUrl': site['page'].format(lang=item['lang']),
            'visitorId': f"qa-smoke-eval-{item['id']}"}
    req = urllib.request.Request(API, data=json.dumps(body, ensure_ascii=False).encode('utf-8'), method='POST',
                                 headers={'Content-Type': 'application/json; charset=utf-8',
                                          'X-Api-Key': site['key'], 'User-Agent': 'SLAtech-Eval-Benchmark/1.0'})
    started = time.time()
    try:
        with urllib.request.urlopen(req, timeout=90) as r:
            status, data = r.status, json.loads(r.read().decode('utf-8'))
    except urllib.error.HTTPError as e:
        status, data = e.code, {'error': e.read().decode('utf-8', 'replace')[:500]}
    except Exception as e:  # transport failure is recorded, not hidden
        status, data = 0, {'error': f'{type(e).__name__}: {e}'}
    return status, data, round((time.time() - started) * 1000)


def main():
    p = argparse.ArgumentParser()
    p.add_argument('questions'); p.add_argument('out')
    p.add_argument('--only', help='id prefix, e.g. med-he')
    p.add_argument('--delay', type=float, default=2.5, help='seconds between questions')
    a = p.parse_args()
    items = json.load(open(a.questions, encoding='utf-8'))
    if a.only:
        items = [i for i in items if i['id'].startswith(a.only)]
    with open(a.out, 'a', encoding='utf-8') as out:
        for n, item in enumerate(items, 1):
            site = SITES[item['id'].split('-')[0]]
            status, data, ms = ask(site, item)
            if status != 200:   # one retry; the second outcome is what gets recorded
                time.sleep(10)
                status, data, ms = ask(site, item)
            out.write(json.dumps({'id': item['id'], 'asked_at': datetime.datetime.now(datetime.timezone.utc).isoformat(timespec='seconds'),
                                  'http_status': status, 'latency_ms': ms, 'response': data}, ensure_ascii=False) + '\n')
            out.flush()
            print(f'{n}/{len(items)} {item["id"]} HTTP {status} {ms} ms')
            time.sleep(a.delay)


if __name__ == '__main__':
    main()
