"""Reproduce the public fee-policy scenarios. No network or private data.
Run: python3 calculate.py
Outputs scenarios.csv and headline-scenarios.csv beside this script.
Uses an unrounded rate formula; actual provider transaction rounding can differ.
"""
from decimal import Decimal as D, ROUND_HALF_UP
from pathlib import Path
import csv
ROOT=Path(__file__).resolve().parent

def fmt(x):return str(x.quantize(D('.01'),rounding=ROUND_HALF_UP))
def scenarios():
    for members in (25,100):
        for price in map(D,('5','10','20','50')):
            gross=price*members
            for provider,platform,processing in (
                ('Gameplan.io launch subscriptions',gross*D('.10'),D('0')),
                ('Patreon standard USD web card',gross*D('.10'),members*(price*D('.029')+D('.30')))):
                fees=platform+processing
                yield {'model_version':'1','members':members,'monthly_price_usd':fmt(price),'gross_usd':fmt(gross),'provider':provider,'platform_component_usd':fmt(platform),'additional_processing_component_usd':fmt(processing),'modeled_transaction_deductions_usd':fmt(fees),'modeled_deduction_percent':fmt(fees/gross*100),'balance_before_excluded_costs_usd':fmt(gross-D(fmt(fees))),'basis':'published-fee scenario, not observed earnings; before transaction rounding; displayed balance subtracts rounded aggregate deduction'}

def main():
    rows=list(scenarios())
    # Independent anchors and invariants, not implementation-mirroring tests.
    gp=next(r for r in rows if r['members']==100 and r['monthly_price_usd']=='10.00' and r['provider'].startswith('Gameplan'))
    pat=next(r for r in rows if r['members']==100 and r['monthly_price_usd']=='10.00' and r['provider'].startswith('Patreon'))
    assert gp['modeled_transaction_deductions_usd']=='100.00'
    assert pat['modeled_transaction_deductions_usd']=='159.00' and pat['balance_before_excluded_costs_usd']=='841.00'
    for row in rows:
        assert D(row['gross_usd'])==D(row['modeled_transaction_deductions_usd'])+D(row['balance_before_excluded_costs_usd'])
    for name,selected in [('scenarios.csv',rows),('headline-scenarios.csv',[r for r in rows if r['members']==100])]:
        with (ROOT/name).open('w',newline='') as f:
            w=csv.DictWriter(f,fieldnames=rows[0].keys());w.writeheader();w.writerows(selected)
    print(f'{len(rows)} provider rows; 8 price/member scenarios; anchors and balance checks passed.')
if __name__=='__main__':main()
