"""lol_model_api_client.py — LoL 10분 승패 예측 모델 API 를 부르는 최소 클라이언트 (표준 라이브러리만).

    python lol_model_api_client.py                  # 예시 입력 3건을 서버에서 받아 차례로 판단
    python lol_model_api_client.py request.json     # 파일의 경기 상태 1건을 판단

BASE 를 바꾸면 다른 서버를 부른다. 키가 필요한 서버면 API_KEY 를 넣는다.
계약(입력 13개·응답 필드·오류 규약)은 api_guide.md 또는 https://p4.sumzip.com/model-api/docs 를 본다.
"""
import json
import sys
import urllib.error
import urllib.request

BASE = "https://p4.sumzip.com/model-api"
API_KEY = ""                                   # 서버가 X-API-Key 를 요구할 때만


def _call(path, payload=None, timeout=15):
    headers = {"Content-Type": "application/json"}
    if API_KEY:
        headers["X-API-Key"] = API_KEY
    data = json.dumps(payload).encode() if payload is not None else None
    req = urllib.request.Request(BASE + path, data=data, headers=headers, method="POST" if data else "GET")
    try:
        with urllib.request.urlopen(req, timeout=timeout) as r:
            return r.status, json.loads(r.read())
    except urllib.error.HTTPError as e:            # 401·422·503 은 여기로 온다 — 본문의 detail 에 이유가 있다
        return e.code, json.loads(e.read() or b"{}")


def health():
    return _call("/health")[1]


def predict(state: dict) -> dict:
    """경기 상태 1건 → label · win_prob_blue · top_factors · anomaly · warnings"""
    status, body = _call("/predict", state)
    if status != 200:
        raise RuntimeError(f"{status}: {body.get('detail')}")
    return body


def predict_batch(states: list) -> list:
    """최대 32건. 입력 순서가 그대로 보존된다."""
    status, body = _call("/predict/batch", {"items": states})
    if status != 200:
        raise RuntimeError(f"{status}: {body.get('detail')}")
    return body["results"]


def coach(state: dict) -> dict:
    """이 상태에서 무엇을 했다면 승률이 얼마나 올랐나 (actions 3개)"""
    status, body = _call("/coach", state)
    if status != 200:
        raise RuntimeError(f"{status}: {body.get('detail')}")
    return body


if __name__ == "__main__":
    h = health()
    print("health:", h["status"], h["model_name"], h["model_version"])
    if h["status"] != "ok":
        sys.exit("모델이 아직 준비 중입니다. 잠시 후 다시 실행하세요.")
    if len(sys.argv) > 1:
        states = [json.load(open(sys.argv[1], encoding="utf-8"))]
    else:
        states = [e["payload"] for e in _call("/examples")[1]]
    for st in states:
        r = predict(st)
        print(f"{r['label']:10s} 블루 승률 {r['win_prob_blue']:.3f}  1위 요인 {r['top_factors'][0]['name']}"
              + (f"  경고 {r['warnings']}" if r["warnings"] else ""))
