"""Python 3.10+, standard library. Run beside schedule.json; rewrites three outputs.
Full scheduled posts only. No clock-to-hand estimate, chip balances or strategy.
"""
from pathlib import Path
import csv
import io
import json

ROOT=Path(__file__).resolve().parent

def calculate(config):
    if type(config.get('schema_version')) is not int or config['schema_version']!=1: raise ValueError('Unsupported schema version')
    seats=config['seats_clockwise']
    if not isinstance(seats,list) or not 3<=len(seats)<=9 or any(not isinstance(s,str) or not s.strip() for s in seats) or len(set(seats))!=len(seats):
        raise ValueError('Use 3-9 distinct nonempty seat labels; heads-up is excluded.')
    if config['first_button'] not in seats: raise ValueError('Unknown first button')
    hands=config['hands']
    if type(hands) is not int or not 1<=hands<=100: raise ValueError('hands must be an integer 1-100')
    boundaries=config['increase_from_hands']
    if not isinstance(boundaries,list) or not boundaries or len(set(boundaries))!=len(boundaries) or any(type(h) is not int or not 1<=h<=hands+1 for h in boundaries): raise ValueError('Invalid increase boundaries')
    for level in ['low','high']:
        amounts=config[level]
        if set(amounts)!={'small_blind','big_blind','big_blind_ante'} or any(type(v) is not int or not 0<=v<=10**9 for v in amounts.values()): raise ValueError('Use nonnegative integer chip amounts')
        if not 0<amounts['small_blind']<=amounts['big_blind']: raise ValueError('Require 0 < SB <= BB')
    if any(config['high'][key]<config['low'][key] for key in config['low']): raise ValueError('High amounts must not decrease')
    if type(config['main_increase_from_hand']) is not int or config['main_increase_from_hand'] not in boundaries: raise ValueError('Main boundary absent')
    rows=[]
    for boundary in boundaries:
        totals={seat:0 for seat in seats}
        for hand in range(1,hands+1):
            button=(seats.index(config['first_button'])+hand-1)%len(seats)
            level='high' if hand>=boundary else 'low'
            amounts=config[level]
            for index,seat in enumerate(seats):
                role='SB' if index==(button+1)%len(seats) else 'BB' if index==(button+2)%len(seats) else 'BTN' if index==button else '-'
                sb=amounts['small_blind'] if role=='SB' else 0
                bb=amounts['big_blind'] if role=='BB' else 0
                ante=amounts['big_blind_ante'] if role=='BB' else 0
                total=sb+bb+ante;totals[seat]+=total
                rows.append(dict(increase_from_hand=boundary,hand=hand,level=level,button=seats[button],seat=seat,role=role,small_blind=sb,big_blind=bb,big_blind_ante=ante,post=total,cumulative=totals[seat]))
    summary=[]
    for boundary in boundaries:
        for seat in seats:
            matching=[r for r in rows if r['increase_from_hand']==boundary and r['seat']==seat]
            summary.append(dict(increase_from_hand=boundary,seat=seat,first_three_posts=sum(r['post'] for r in matching if r['hand']<=3),all_hand_posts=sum(r['post'] for r in matching)))
    return {'units':'chips','model':'gross full scheduled posts; no pot returns, balances or decision EV','rows':rows,'summary':summary}

def csv_bytes(rows):
    stream=io.StringIO(newline='')
    writer=csv.DictWriter(stream,fieldnames=list(rows[0]),lineterminator='\n')
    writer.writeheader();writer.writerows(rows)
    return stream.getvalue().encode('utf-8')

if __name__=='__main__':
    result=calculate(json.loads((ROOT/'schedule.json').read_text(encoding='utf-8')))
    (ROOT/'results.json').write_text(json.dumps(result,indent=2)+'\n',encoding='utf-8',newline='\n')
    (ROOT/'posts.csv').write_bytes(csv_bytes(result['rows']))
    (ROOT/'summary.csv').write_bytes(csv_bytes(result['summary']))
    print(f"Wrote {len(result['rows'])} seat-hand rows and {len(result['summary'])} summaries.")
