"""Educational Jev example. Fixture by default; --live makes a billed API call."""
import argparse
import json
import math
import os
import urllib.request
import urllib.error
from copy import deepcopy

STATE = {'text': "Let's schedule the review next Thursday afternoon.", 'reference_date': '2026-09-21', 'timezone': 'America/Los_Angeles', 'convention': 'next weekday means strictly after the reference date'}
QUESTIONS = {'relative_expression': {'type': 'choice', 'instructions': 'Which listed temporal expression appears in text?', 'criteria': {'next_weekday': 'A named next weekday', 'explicit_date': 'A literal calendar date', 'other': 'No supported expression'}}, 'weekday': {'type': 'choice', 'instructions': 'Which weekday is named?', 'criteria': {'Monday': None, 'Tuesday': None, 'Wednesday': None, 'Thursday': None, 'Friday': None, 'Saturday': None, 'Sunday': None, 'none': None}}, 'time_period': {'type': 'choice', 'instructions': 'Which period of day is named?', 'criteria': {'morning': None, 'afternoon': None, 'evening': None, 'unspecified': None}}}
FIXTURE = {'relative_expression': {'type': 'choice', 'choice': 'next_weekday', 'confidence': 0.93, 'probabilities': {'next_weekday': 0.9533333333333334, 'explicit_date': 0.023333333333333317, 'other': 0.023333333333333317}}, 'weekday': {'type': 'choice', 'choice': 'Thursday', 'confidence': 0.94, 'probabilities': {'Monday': 0.007499999999999999, 'Tuesday': 0.007499999999999999, 'Wednesday': 0.007499999999999999, 'Thursday': 0.9475, 'Friday': 0.007499999999999999, 'Saturday': 0.007499999999999999, 'Sunday': 0.007499999999999999, 'none': 0.007499999999999999}}, 'time_period': {'type': 'choice', 'choice': 'afternoon', 'confidence': 0.9, 'probabilities': {'morning': 0.024999999999999984, 'afternoon': 0.925, 'evening': 0.024999999999999984, 'unspecified': 0.024999999999999984}}}

def decide(answers, state):
    from datetime import date, timedelta
    if min(value["confidence"] for value in answers.values()) < .85:
        return {"route": "clarify", "scheduled": False}
    weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
    weekday = answers["weekday"]["choice"]
    if answers["relative_expression"]["choice"] != "next_weekday" or weekday not in weekdays:
        return {"route": "unsupported_expression", "scheduled": False}
    reference = date.fromisoformat(state["reference_date"])
    delta = (weekdays.index(weekday) - reference.weekday()) % 7 or 7
    resolved = reference + timedelta(days=delta)
    return {"date": resolved.isoformat(), "timezone": state["timezone"],
            "period": answers["time_period"]["choice"], "scheduled": False,
            "route": "confirm_exact_time"}

def validate(answers):
    if not isinstance(answers, dict):
        raise ValueError("Answer map missing")
    for name, question in QUESTIONS.items():
        answer = answers.get(name)
        if not isinstance(answer, dict) or answer.get("type") != question["type"]:
            raise ValueError("Missing or unexpected answer type: " + name)
        field = {"choice": "choice", "score": "score", "noul": "noul"}[question["type"]]
        value = answer.get(field)
        if field == "choice":
            if value not in question["criteria"]:
                raise ValueError("Unknown category: " + name)
        elif not isinstance(value, (int, float)) or isinstance(value, bool) or not math.isfinite(value):
            raise ValueError("Invalid number: " + name)
        elif not 0 <= value <= (1 if field == "noul" else len(question["criteria"])-1):
            raise ValueError("Out-of-range answer: " + name)
        if field != "noul":
            c = answer.get("confidence")
            if not isinstance(c, (int, float)) or isinstance(c, bool) or not math.isfinite(c) or not 0 <= c <= 1:
                raise ValueError("Invalid confidence: " + name)
    return answers

def evaluate(live=False):
    if not live:
        return {"model": "fixture-not-a-model-run", "answers": deepcopy(FIXTURE)}
    key = os.environ.get("TYPESAFE_API_KEY", "").strip()
    if not key:
        raise ValueError("Set TYPESAFE_API_KEY in the environment for --live")
    payload = {"model": "jev-1.13.0", "state": STATE, "questions": QUESTIONS}
    request = urllib.request.Request("https://api.typesafe.ai/v1/systemone",
        data=json.dumps(payload).encode(), method="POST",
        headers={"Authorization": "Bearer " + key, "Content-Type": "application/json"})
    # A bounded single call. The application can add a bounded retry policy.
    with urllib.request.urlopen(request, timeout=30) as response:
        return json.load(response)

def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--live", action="store_true")
    args = parser.parse_args()
    try:
        result = evaluate(args.live)
        decision = decide(validate(result["answers"]), STATE)
    except urllib.error.HTTPError as error:
        print(json.dumps({"route": "review", "executed": False, "http_status": error.code}))
        raise SystemExit(1)
    except (ValueError, KeyError, TypeError, urllib.error.URLError, TimeoutError):
        print(json.dumps({"route": "review", "executed": False, "reason": "evaluation_failed"}))
        raise SystemExit(1)
    print(json.dumps({"mode": "live" if args.live else "illustrative_fixture",
        "model": result.get("model"), "decision": decision,
        "answers": result["answers"]}, indent=2))

if __name__ == "__main__":
    main()
