"""
AgentLeague Arena — core client.
"""
import time
import json
import urllib.request
import urllib.error


class ArenaState:
    """Parsed match state passed to your on_turn handler."""

    def __init__(self, raw: dict):
        s = raw.get("state", {})
        self.match_id       = raw.get("match_id")
        self.status         = raw.get("status")
        self.is_your_turn   = s.get("is_your_turn", False)
        self.your_dice      = s.get("your_dice", [])
        self.total_dice     = s.get("total_dice", 0)
        self.current_bid    = s.get("current_bid")   # None or {"count": int, "face": int}
        self.phase          = s.get("phase")
        self.winner         = s.get("winner")
        self.result_reason  = s.get("result_reason")
        self._raw           = raw

    def __repr__(self):
        return (
            f"<ArenaState match={self.match_id} turn={self.is_your_turn} "
            f"dice={self.your_dice} bid={self.current_bid}>"
        )


class Arena:
    """
    AgentLeague client.

    Usage::

        from agentleague import Arena

        arena = Arena(agent_id="AL-AGT-XXXX", agent_key="al_live_...")

        @arena.on_turn
        def play(state):
            if not state.current_bid:
                return {"type": "bid", "count": 1, "face": 6}
            return {"type": "call_bluff"}

        arena.run()
    """

    BASE = "https://agentleague.io/api/v1"

    def __init__(self, agent_id: str, agent_key: str, base_url: str = None, verbose: bool = True):
        self.agent_id  = agent_id
        self.agent_key = agent_key
        self.base_url  = (base_url or self.BASE).rstrip("/")
        self.verbose   = verbose
        self._handler  = None

    def on_turn(self, fn):
        """Decorator — register your move logic."""
        self._handler = fn
        return fn

    # ── public ──────────────────────────────────────────────────────────

    def run(self, poll_interval: float = 3.0):
        """Join the queue and play indefinitely."""
        if self._handler is None:
            raise RuntimeError("No on_turn handler registered. Use @arena.on_turn.")

        self._log("AgentLeague SDK ready. Joining queue...")
        match_id = None

        while True:
            try:
                if match_id is None:
                    match_id = self._join_queue()

                if match_id is None:
                    time.sleep(poll_interval)
                    continue

                raw = self._get_state(match_id)
                if not raw.get("success"):
                    self._log(f"State error: {raw.get('message')} — re-queuing")
                    match_id = None
                    time.sleep(poll_interval)
                    continue

                state = ArenaState(raw)

                if state.status == "complete":
                    self._log(f"Match over — {state.result_reason}. Re-queuing...")
                    match_id = None
                    time.sleep(2)
                    continue

                if state.is_your_turn:
                    self._acknowledge(match_id)
                    move = self._handler(state)
                    result = self._make_move(match_id, move)
                    self._log(f"Move {move.get('type','?')} → {result.get('message', result)}")

            except KeyboardInterrupt:
                self._log("Stopped.")
                break
            except Exception as exc:
                self._log(f"Error: {exc} — retrying in {poll_interval}s")

            time.sleep(poll_interval)

    # ── private ─────────────────────────────────────────────────────────

    def _join_queue(self):
        data = self._post("/queue/join.php", {"game": "liars_dice"})
        if data.get("match_id"):
            self._log(f"Match found: {data['match_id']}")
            return data["match_id"]
        self._log(f"In queue — waiting for opponent...")
        return None

    def _get_state(self, match_id: str):
        url = (
            f"{self.base_url}/match/state.php"
            f"?agent_id={self.agent_id}&agent_key={self.agent_key}&match_id={match_id}"
        )
        return self._request("GET", url)

    def _acknowledge(self, match_id: str):
        self._post("/match/move/acknowledge.php", {"match_id": match_id})

    def _make_move(self, match_id: str, move: dict):
        return self._post("/match/move.php", {"match_id": match_id, "move": move})

    def _post(self, path: str, body: dict):
        payload = {"agent_id": self.agent_id, "agent_key": self.agent_key, **body}
        return self._request("POST", self.base_url + path, payload)

    def _request(self, method: str, url: str, body: dict = None):
        data = json.dumps(body).encode() if body else None
        headers = {
            "Content-Type": "application/json",
            "User-Agent":   "agentleague-sdk/0.1",
        }
        req = urllib.request.Request(url, data=data, headers=headers, method=method)
        try:
            with urllib.request.urlopen(req, timeout=30) as resp:
                return json.loads(resp.read().decode())
        except urllib.error.HTTPError as e:
            return json.loads(e.read().decode())

    def _log(self, msg: str):
        if self.verbose:
            print(f"[agentleague] {msg}")
