#!/usr/bin/env python3
"""Blind RWS draw for Object B monitoring.

Source of truth for deck data: ekelen/tarot-api (Rider–Waite–Smith JSON).
Repo: https://github.com/ekelen/tarot-api
API:  https://tarotapi.dev

Method: Fisher–Yates via secrets.SystemRandom, no replacement, reverse p=0.5.
Do NOT adjust draws to prior metric snapshots — interpret only after cards exist.
"""
from __future__ import annotations

import argparse
import json
import secrets
from datetime import datetime, timezone
from pathlib import Path

HERE = Path(__file__).resolve().parent
DECK_PATH = HERE / "card_data.rws.json"

MAJORS_RU = {
    "The Fool": "Шут",
    "The Magician": "Маг",
    "The High Priestess": "Жрица",
    "The Empress": "Императрица",
    "The Emperor": "Император",
    "The Hierophant": "Иерофант",
    "The Lovers": "Влюблённые",
    "The Chariot": "Колесница",
    "Strength": "Сила",
    "The Hermit": "Отшельник",
    "Wheel of Fortune": "Колесо",
    "Justice": "Справедливость",
    "The Hanged Man": "Повешенный",
    "Death": "Смерть",
    "Temperance": "Умеренность",
    "The Devil": "Дьявол",
    "The Tower": "Башня",
    "The Star": "Звезда",
    "The Moon": "Луна",
    "The Sun": "Солнце",
    "Judgement": "Суд",
    "The World": "Мир",
    "The Last Judgment": "Суд",
}

SUIT = {"wands": "♣", "cups": "♥", "swords": "♠", "pentacles": "♦"}
COURT = {"page": "Паж", "knight": "Рыцарь", "queen": "Королева", "king": "Король"}


def load_deck() -> list[dict]:
    raw = json.loads(DECK_PATH.read_text())
    cards = raw["cards"] if isinstance(raw, dict) and "cards" in raw else raw
    if len(cards) != 78:
        raise SystemExit(f"expected 78 cards, got {len(cards)}")
    return cards


def label_ru(c: dict, rev: bool) -> str:
    name = c["name"]
    if c.get("type") == "major" or name in MAJORS_RU or name.startswith("The "):
        # majors in ekelen use type major; Judgement may be "The Last Judgment"
        base = MAJORS_RU.get(name) or MAJORS_RU.get(name.replace("The Last Judgment", "Judgement"), name)
        if name == "Wheel of Fortune":
            base = "Колесо"
    else:
        suit = SUIT.get(c.get("suit"), "?")
        val = c.get("value")
        if val in COURT:
            base = f"{COURT[val]}{suit}"
        elif val == "ace":
            base = f"Туз{suit}"
        else:
            base = f"{c.get('value_int', val)}{suit}"
    return f"{base}{' (пер.)' if rev else ''}"


def draw(metrics: list[str], layers: int = 3, per_layer: int = 3, reverse_p: float = 0.5) -> dict:
    rng = secrets.SystemRandom()
    deck = load_deck()[:]
    rng.shuffle(deck)
    need = len(metrics) * layers * per_layer
    if need > 78:
        raise SystemExit(f"need {need} cards > 78")
    out = {
        "source": "ekelen/tarot-api static/card_data.json (RWS)",
        "repo": "https://github.com/ekelen/tarot-api",
        "api": "https://tarotapi.dev",
        "method": f"secrets.SystemRandom shuffle · no replacement · reverse_p={reverse_p}",
        "drawn_at": datetime.now(timezone.utc).astimezone().isoformat(timespec="seconds"),
        "spreads": {},
    }
    i = 0
    layer_names = ["osn", "utochn", "slepa"][:layers]
    for m in metrics:
        spread = {}
        for layer in layer_names:
            trio = []
            for _ in range(per_layer):
                c = deck[i]
                i += 1
                rev = rng.random() < reverse_p
                trio.append(
                    {
                        "name": c["name"],
                        "name_short": c["name_short"],
                        "label_ru": label_ru(c, rev),
                        "reversed": rev,
                        "meaning": c["meaning_rev"] if rev else c["meaning_up"],
                    }
                )
            spread[layer] = trio
        out["spreads"][m] = spread
    out["cards_used"] = i
    return out


def main() -> None:
    ap = argparse.ArgumentParser(description="Blind RWS draw (ekelen deck)")
    ap.add_argument("--metrics", nargs="+", required=True)
    ap.add_argument("-o", "--out", type=Path, required=True)
    args = ap.parse_args()
    data = draw(args.metrics)
    args.out.write_text(json.dumps(data, ensure_ascii=False, indent=2))
    print(f"wrote {args.out} ({data['cards_used']} cards)")
    for m, sp in data["spreads"].items():
        print(f"\n== {m}")
        for layer, trio in sp.items():
            print(f"  {layer}: " + " · ".join(x["label_ru"] for x in trio))


if __name__ == "__main__":
    main()
