#!/usr/bin/env python3
"""Prototype Bloom (Center Circle) generator — prints real sample wheels so we
can feel the quality before building any UI. The validated logic here becomes
goodnews/bloom.py."""
import hashlib
import json
import random
from pathlib import Path

_DATA = Path(__file__).resolve().parents[1] / "goodnews" / "data"
d = json.loads((_DATA / "bloom_words.json").read_text())
ACCEPT = d["accept"]
COMMON = set(d["common"])
ACCEPT_LS = [(w, frozenset(w)) for w in ACCEPT]
# Off-brand words we never CELEBRATE as the day's pangram (accept-list unaffected).
AVOID = set(json.loads((_DATA / "bloom_avoid.json").read_text()))

# Candidate wheels = letter-sets of COMMON 7-distinct-letter words (so the day's
# pangram is always a recognizable word). No 'S' already guaranteed by the list.
PANGRAM_SETS: dict[frozenset, list[str]] = {}
for w in COMMON:
    s = frozenset(w)
    if len(s) == 7:
        PANGRAM_SETS.setdefault(s, []).append(w)

MIN_WORDS, MAX_WORDS, MIN_COMMON, TOP_TIER = 24, 60, 14, 0.70


def score(w: str) -> int:
    return 1 if len(w) == 4 else len(w)


def build(letters: frozenset, center: str):
    words = [w for w, s in ACCEPT_LS if center in w and s <= letters]
    pangrams = [w for w in words if frozenset(w) == letters]
    commons = [w for w in words if w in COMMON]
    max_score = sum(score(w) for w in words) + 7 * len(pangrams)
    common_score = sum(score(w) for w in commons) + 7 * len([w for w in pangrams if w in COMMON])
    return words, pangrams, commons, max_score, common_score


def valid(letters, center):
    words, pangrams, commons, max_score, common_score = build(letters, center)
    if not (MIN_WORDS <= len(words) <= MAX_WORDS):
        return None
    # The DISPLAY pangram must be calm + recognizable: common, not on the avoid
    # list. (Off-brand pangrams like LUCIFER/VOMITING are still accepted if typed,
    # just never the day's celebrated word.)
    display = [p for p in pangrams if p in COMMON and p not in AVOID]
    if not display or len(commons) < MIN_COMMON:
        return None
    if common_score < TOP_TIER * max_score:   # top tier reachable from common vocab
        return None
    return words, sorted(display, key=len), commons, max_score, common_score


def generate(date: str):
    rng = random.Random(int(hashlib.sha256(f"bloom:{date}".encode()).hexdigest(), 16))
    sets = list(PANGRAM_SETS)
    rng.shuffle(sets)
    for s in sets:
        centers = sorted(s)
        rng.shuffle(centers)
        for c in centers:
            res = valid(s, c)
            if res:
                return s, c, res
    return None


print(f"loaded accept={len(ACCEPT)} common={len(COMMON)} | candidate wheels={len(PANGRAM_SETS)}\n")
for date in ("2026-06-15", "2026-06-16", "2026-06-17", "2026-06-18", "2026-06-19"):
    s, c, (words, pangrams, commons, max_score, common_score) = generate(date)
    outer = sorted(s - {c})
    tiers = {"Sprouting": 0, "Budding": int(0.08 * max_score),
             "Blooming": int(0.30 * max_score), "Flourishing": int(0.70 * max_score)}
    longest = sorted(words, key=len, reverse=True)[:3]
    sample = sorted(random.Random(1).sample(words, min(16, len(words))))
    print(f"── {date} ──  center [{c.upper()}]  outer {[x.upper() for x in outer]}")
    print(f"   words={len(words)} (common={len(commons)})  pangram(s)={[p.upper() for p in pangrams]}")
    print(f"   max_score={max_score}  tiers={tiers}")
    print(f"   longest={longest}  sample={sample}\n")
