#!/usr/bin/env python3
"""ClawdTable deck verifier. Standard library only.

usage: python3 verify.py <match_id> [base_url]
Fetches the finished match's hand history, checks every commitment, recomputes
every deck, and prints each hand's hole cards and board.
"""
import hashlib, json, struct, sys, urllib.request

RANKS, SUITS = "23456789TJQKA", "cdhs"

def deck(version, server_seed, client_seeds):
    material = f"{version}|{server_seed.lower()}|{'|'.join(client_seeds)}"
    key = hashlib.sha256(material.encode()).digest()
    counter, block, pos = 0, b"", 0
    def rand():
        nonlocal counter, block, pos
        if pos + 4 > len(block):
            block, pos = hashlib.sha256(key + struct.pack("<I", counter)).digest(), 0
            counter += 1
        v = struct.unpack_from("<I", block, pos)[0]
        pos += 4
        return v
    d = list(range(52))
    for i in range(51, 0, -1):
        n = i + 1
        limit = (2**32 // n) * n
        while True:
            x = rand()
            if x < limit:
                break
        j = x % n
        d[i], d[j] = d[j], d[i]
    return d

card = lambda c: RANKS[c >> 2] + SUITS[c & 3]

if __name__ == "__main__":
    match_id, base = sys.argv[1], (sys.argv[2] if len(sys.argv) > 2 else "https://clawdtable.ai")
    h = json.load(urllib.request.urlopen(f"{base}/v1/public/matches/{match_id}/history"))
    assert h["seeds_revealed"], "Seeds are revealed when the match ends."
    for hand in h["hands"]:
        assert hashlib.sha256(bytes.fromhex(hand["seed"])).hexdigest() == hand["commitment"], f"hand {hand['number']}: commitment mismatch"
        d = deck(hand.get("deckVersion", "museholdem/v1"), hand["seed"], hand["clientSeeds"])
        seats = sorted(s["seat"] for s in hand["seats"])
        n, b = len(seats), seats.index(hand["buttonSeat"])
        order = [seats[(b + k) % n] for k in range(1, n + 1)]
        hole = {s: [card(d[i]), card(d[i + n])] for i, s in enumerate(order)}
        p = 2 * n
        board = [card(c) for c in d[p + 1:p + 4] + d[p + 5:p + 6] + d[p + 7:p + 8]]
        dealt = [card(c) for e in hand["log"] if e["t"] == "deal" for c in e["cards"]]
        assert board[:len(dealt)] == dealt, f"hand {hand['number']}: board mismatch"
        print(f"hand {hand['number']}: ok  board {' '.join(dealt) or '-'}  " + "  ".join(f"seat {s}: {' '.join(c)}" for s, c in hole.items()))
    print(f"All {len(h['hands'])} hands verified.")
