"""5.10 Self-hosted GPU payback calculator. Reads scenarios from scenarios.py and computes annual replaced cloud spend, power cost, and simple payback period.

Usage:
    python3 payback.py              # Run all scenarios in scenarios.py, plus your MY_SETUP
    python3 payback.py --load 0.25  # Set utilization to 25% for all API scenarios to test the full-load assumption
Standard library only; runs on Python 3.8+.
"""
import argparse

from scenarios import MY_SETUP, SCENARIOS

HOURS_PER_YEAR = 24 * 365


def yearly(s, load):
    """Return (annual replaced cloud spend, annual power cost, summary note)."""
    if s['compare'] == 'api':
        hours = HOURS_PER_YEAR * load
        out_m = s['output_tok_per_s'] * 3600 * hours / 1e6                     # Annual output in millions of tokens
        h = s['cache_hit_rate']
        in_price = h * s['price_input_cached'] + (1 - h) * s['price_input']      # Blended price per 1M input tokens
        per_m_out = s['input_per_output'] * in_price + s['price_output']         # Cloud API cost per 1M output tokens generated
        value = out_m * per_m_out
        note = f'{load:.0%} load, {out_m:,.0f}M output tokens/year, ${per_m_out:,.2f} cloud API value per 1M output tokens'
    elif s['compare'] == 'subscription':
        hours = HOURS_PER_YEAR          # Seat count is already converted from full-load server capacity; --load does not apply here
        value = s['seats'] * s['usd_per_seat_year']
        note = f'{s["seats"]} seat(s) × ${s["usd_per_seat_year"]:,}/year'
    elif s['compare'] == 'my_bill':
        hours = s.get('hours_per_day', 24) * 365
        value = s['monthly_api_bill_usd'] * 12
        note = f'monthly bill ${s["monthly_api_bill_usd"]:,} × 12, running {s.get("hours_per_day", 24)} hours/day'
    else:
        raise ValueError(s['compare'])
    power = s['power_kw'] * s.get('pue', 1.0) * hours * s['usd_per_kwh']
    return value, power, note


def payback(hw, net):
    if net <= 0:
        return 'Never pays back (annual cloud savings do not cover electricity)'
    lo, hi = (hw, hw) if isinstance(hw, (int, float)) else hw
    y = (lo / net, hi / net)
    fmt = lambda v: f'{v:.2f} years ({v * 12:.1f} months)'
    return fmt(y[0]) if lo == hi else f'{y[0]:.2f}–{y[1]:.2f} years ({y[0] * 12:.1f}–{y[1] * 12:.1f} months)'


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument('--load', type=float, default=1.0, help='Utilization rate for API scenarios: fraction of the year running at full load (default: 1.0, i.e., 24/7 full load)')
    args = ap.parse_args()
    for s in SCENARIOS + [MY_SETUP]:
        value, power, note = yearly(s, args.load)
        hw = s['hardware_usd']
        hw_txt = f'${hw:,}' if isinstance(hw, (int, float)) else f'${hw[0]:,}–${hw[1]:,}'
        print(f'\n## {s["name"]}')
        print(f'- Hardware {hw_txt}; {note}')
        print(f'- Annual cloud spend replaced: ${value:,.2f}, electricity: ${power:,.2f}, net savings: ${value - power:,.2f}')
        print(f'- Simple payback period: {payback(hw, value - power)}')
    print('\nCounts hardware and electricity only. Rack space, networking, engineering labor, redundancy, depreciation, and resale value are excluded, so real payback takes longer.')


if __name__ == '__main__':
    main()
