#!/usr/bin/env python3
"""Builds ~/StickBrawl-v3/v4/feedback/51_build.html from the TF checklist + the merges log.
Usage: python3 make_build_board.py ["optional note"]
Paths: the pages folder is this script's parent (the Mac's ~/StickBrawl-v3/v4/feedback, or a clone of farisbasha/Stickbash-pages
on the build VM); the code repo is $STICKBASH_REPO (default: the Mac's integration worktree; the VM sets /root/stickbash/v4)."""
import re, json, os, sys, datetime, html
HERE = os.path.dirname(os.path.abspath(__file__))
PAGES = os.path.dirname(HERE)
REPO = os.environ.get('STICKBASH_REPO', '/Volumes/Workspace/Projects/StickFight-dev')
CHK = REPO + '/Docs/plan/v4/tf/CHECKLIST.md'
MERGES = os.path.join(HERE, 'tf_merges.json')
OUT = os.path.join(PAGES, '51_build.html')
STREAMS = [('TF-MODES', 'MODES', 'Who-How-Go menu, 7 themed modes, the Bash Ring, moments, maps', '36 · 37'),
           ('TF-TEAMS', 'TEAMS', 'Team colours fix, one-colour shades + markers, line-up intro, find me, arrow jitter', '43'),
           ('TF-FINISH', 'FINISHERS', 'Round-ending finishers, 4 reach styles, 76 kills, KILLS tab', '38 · 39'),
           ('TF-SKINFX', 'SKIN KILL FX', '238 brutal skin kills, SAVAGE gore, KO FX retired', '40'),
           ('TF-SPELLS', 'SPELLS', '12 spells, comeback roll, rune circles, top banner', '44'),
           ('TF-FEEL', 'FEEL', 'Stun flash, vivid guns, 10 new reloads, backpedal, gun trip', '41 · 42 · 49 · 50'),
           ('TF-MAPS', 'MAPS', 'Every map relit: moonlit diorama, 5 layers, moon rims, lively motion, full night', '51'),
           ('TF-META', 'META', 'Coin packs, practice arena picker, About signature, gloats for everything', '45 · 46 · 47 · 48'),
           ('TF-CLEAN', 'CLEAN SCREEN', 'Multiplayer declutter: about you full, the round always, the rest a whisper; budget 3', '52'),
           ('TF-POLISH', 'POLISH', 'Rooms READY, training skip, the finisher lesson, idle reload, the start spotlight, kill text, gloat at the kill, utility gun damage', '56'),
           ('TF-KILLS', 'KILL ANIMATIONS', 'Page 58: ~930 round-ending films (25 / 15 per weapon + 7 skins, fists 25) + 175 mid-round small kills; ported only after the user approves all pages', '58'),
           ('KILL SYSTEM', 'KILL SYSTEM', 'Agreed 24 Oct: cleanup now (CU), the kill system after the approval gate (KS): finisher merge, mid-round zone, 18 arenas, destruction, 6 gore levels, switches', '59'),
           ('TF-CHEST', 'CHESTS', 'The chest opening rebuilt: 4 bespoke chests, tap charge, tier flip, one-by-one reveals, LEGENDARY moment', '-')]
txt = open(CHK).read()
secs = re.split(r'\n## ', txt)
data = []
for key, name, line, pages in STREAMS:
    sec = next((s for s in secs if s.startswith(key)), '')
    rows = []
    for m in re.finditer(r'^- \[(.)\] (.+)$', sec, re.M):
        st = {' ': 'todo', '~': 'doing', 'x': 'done', '!': 'blocked'}.get(m.group(1), 'todo')
        idm = re.search(r'\b([A-Z]{1,2}\d\d)\b (.+)$', m.group(2))
        if not idm: continue
        rows.append({'id': idm.group(1), 's': st, 't': idm.group(2)[:160]})
    data.append({'k': key, 'n': name, 'line': line, 'pages': pages, 'rows': rows})
merges = json.load(open(MERGES)) if os.path.exists(MERGES) else []
state = json.load(open(MERGES.replace('merges', 'state'))) if os.path.exists(MERGES.replace('merges', 'state')) else {}
now = datetime.datetime.now().strftime('%d %b %H:%M')
note = sys.argv[1] if len(sys.argv) > 1 else state.get('note', '')
D = {'updated': now, 'note': note, 'streams': data, 'merges': merges, 'state': state.get('streams', {})}
tpl = open(os.path.join(HERE, 'build_board_tpl.html')).read()
open(OUT, 'w').write(tpl.replace('/*DATA*/', 'const D = ' + json.dumps(D) + ';'))
done = sum(1 for s in data for r in s['rows'] if r['s'] == 'done'); tot = sum(len(s['rows']) for s in data)
print(f'board written: {done}/{tot} done')
