#!/usr/bin/env python3
"""Independent decimal reference for Retire Growth model 1.0.0.
Run: python3 public/audit/verify_model.py > public/audit/model-v1.json
Uses monthly iteration rather than the application's closed-form annuity.
No network requests or third-party packages.
"""
from decimal import Decimal, getcontext
import json
getcontext().prec = 70
D = Decimal
BASE = dict(age=32, retirementAge=65, savings=80000, monthly=1500,
            spending=4000, annualReturn=7, inflation=3, withdrawal=4)

def reference(inputs):
    years = inputs['retirementAge'] - inputs['age']
    months = years * 12
    growth = (1 + D(inputs['annualReturn']) / 100) / (1 + D(inputs['inflation']) / 100)
    month_growth = growth ** (D(1) / 12)
    target = D(inputs['spending']) * 12 / (D(inputs['withdrawal']) / 100)
    coast = target / growth ** years
    balance = D(inputs['savings'])
    first_month = 0 if balance >= coast else None
    annuity = D(0)
    for month in range(1, months + 1):
        balance = balance * month_growth + D(inputs['monthly'])
        annuity = annuity * month_growth + 1
        threshold = target / month_growth ** (months - month)
        if first_month is None and balance >= threshold:
            first_month = month
    no_deposits = D(inputs['savings']) * growth ** years
    required = max(D(0), (target - no_deposits) / annuity)
    def usd(value): return str(value.quantize(D('0.00000001')))
    return dict(target=usd(target), coast=usd(coast), coastMonth=first_month,
                balance=usd(balance), noDeposits=usd(no_deposits),
                requiredMonthly=usd(required))

variants = [('default', {}), ('no-additional-deposits', {'monthly': 0}),
            ('zero-real-growth', {'annualReturn': 3}),
            ('negative-real-growth', {'annualReturn': 2}),
            ('zero-spending-target', {'spending': 0})]
result = dict(modelVersion='1.0.0', reference='Python decimal, 70-digit monthly recurrence',
              cases=[dict(name=name, inputs={**BASE, **changes}, expected=reference({**BASE, **changes}))
                     for name, changes in variants],
              accumulationBenchmark=dict(principal=80000, years=33, annualRatePercent=7, monthlyDeposit=0,
                  effectiveAnnualNominal=str((D(80000) * D('1.07') ** 33).quantize(D('.01'))),
                  nominalAprMonthly=str((D(80000) * (1 + D('.07')/12) ** 396).quantize(D('.01')))))
print(json.dumps(result, indent=2))
