"""Reproduce FinanceFirst v1.0 hypothetical outputs. Python 3; no packages/network.
Run beside plan-inputs.json. All amounts USD; no assigned probabilities.
"""
import csv,json
from pathlib import Path
from decimal import Decimal as D
p=Path(__file__).resolve().parent
plans=json.loads((p/'plan-inputs.json').read_text())
def share(x,a):
 x=D(str(x));d=D(str(a['deductible_usd']))
 return min(D(a['out_of_pocket_max_usd']),min(x,d)+D(str(a['coinsurance']))*max(x-d,D(0)))
def cost(x,a):return D(a['annual_worker_premium_usd'])+share(x,a)-D(a['employer_hsa_usd'])
rows=[]
for x in [0,500,3000,10000,18500,20250,20500,50000]:
 for a in plans:
  rows.append(dict(plan=a['plan'],annual_covered_allowed_charges_usd=x,annual_worker_premium_usd=a['annual_worker_premium_usd'],member_cost_sharing_usd=float(share(x,a)),premium_plus_cost_sharing_usd=float(cost(x,a)+D(a['employer_hsa_usd'])),employer_hsa_usd=a['employer_hsa_usd'],funding_adjusted_economic_cost_usd=float(cost(x,a)),type='hypothetical single-person scenario; not observed plans',caveat='identical covered prices; full-year coverage; received owned employer HSA; no tax effects; not cash outflow'))
with (p/'scenarios-reproduced.csv').open('w',newline='') as f:
 w=csv.DictWriter(f,fieldnames=list(rows[0]));w.writeheader();w.writerows(rows)
assert cost(10000,plans[1])-cost(10000,plans[0])==350
assert share(3000,plans[0])-share(3000,plans[1])==1600
assert cost(20250,plans[0])==cost(20250,plans[1])==7860
assert cost(50000,plans[0])-cost(50000,plans[1])==50
for a in plans:
 previous=D(-1)
 for x in range(50001):
  s=share(x,a);assert previous<=s<=min(x,a['out_of_pocket_max_usd']);previous=s
early=[]
for a,available in [(plans[0],0),(plans[0],750),(plans[1],0)]:
 early.append(dict(plan=a['plan'],early_service_allowed_charge_usd=3000,member_liability_usd=float(share(3000,a)),employer_funds_available_usd=available,outside_cash_usd=float(share(3000,a)-available)))
with (p/'early-bill-reproduced.csv').open('w',newline='') as f:
 w=csv.DictWriter(f,fieldnames=list(early[0]));w.writeheader();w.writerows(early)
print('PASS: 16 scenario rows, 3 early-bill rows, headline ties and 100002 bounds/monotonicity checks')
