"""Independent Decimal reconstruction of the published Microsoft DCF.

Run beside the downloaded inputs/results JSON files; no third-party packages.
"""
from decimal import Decimal, getcontext
from pathlib import Path
import json

getcontext().prec = 40
base = Path(__file__).resolve().parent
inputs_path = base / 'inputs.json'
results_path = base / 'results.json'
if not inputs_path.exists():
    inputs_path = base / 'microsoft-valuation-inputs.json'
    results_path = base / 'microsoft-valuation-results.json'
inputs = json.loads(inputs_path.read_text(), parse_float=Decimal, parse_int=Decimal)
published = json.loads(results_path.read_text(), parse_float=Decimal, parse_int=Decimal)
r, a = inputs['reported'], inputs['common']
D = Decimal

def independently_value(case, rate=None, growth=None, shift=D(0)):
    rate = a['wacc'] if rate is None else rate
    growth = a['terminal_growth'] if growth is None else growth
    revenues = dict(r['revenue'])
    cashflows = []
    for i in range(10):
        previous = sum(revenues.values())
        revenues = {name: amount * (1 + case['growth'][name][i] + (shift if name == 'Cloud' else 0))
                    for name, amount in revenues.items()}
        total = sum(revenues.values())
        profit = total * case['margin'][i] * (1 - a['tax'])
        cash = profit - total * (case['capex'][i] - case['da'][i]) - (total - previous) * a['nwc_per_incremental_revenue']
        cashflows.append(cash)
    terminal_cash = profit * (1 + growth) * (1 - growth / case['terminal_roic'])
    discounted = sum(c / (1+rate)**i for i, c in enumerate(cashflows, 1))
    terminal_pv = terminal_cash / (rate-growth) / (1+rate)**10
    net_assets = r['cash_and_short_investments'] - a['operating_cash_reserve'] - r['debt_face'] - r['finance_lease_liability']
    return (discounted + terminal_pv + net_assets) / r['shares_diluted'], cashflows

for name, case in inputs['scenarios'].items():
    value, cash = independently_value(case)
    actual = published['scenarios'][name]
    assert abs(value-actual['per_share']) < D('0.00000001'), (name,value,actual['per_share'])
    assert len(cash) == len(actual['rows']) == 10
    for modeled, exported in zip(cash, actual['rows']):
        assert abs(modeled-exported['fcff']) < D('0.00000001')
    print(f'{name}: ${value:.2f}; all ten cash flows reconcile')

for row in published['sensitivity']:
    value, _ = independently_value(inputs['scenarios']['Base'],row['wacc'],row['g'])
    assert abs(value-row['value']) < D('0.00000001')
price_from_growth,_=independently_value(inputs['scenarios']['Base'],shift=published['reverse_cloud_shift'])
price_from_rate,_=independently_value(inputs['scenarios']['Base'],rate=published['implied_discount'])
assert abs(price_from_growth-r['price']) < D('0.00000001')
assert abs(price_from_rate-r['price']) < D('0.00000001')
assert independently_value(inputs['scenarios']['Base'],D('.08'))[0] > independently_value(inputs['scenarios']['Base'],D('.10'))[0]
assert sum(r['revenue'].values()) == D('331.839')
assert r['cfo']-r['cash_capex']-r['sbc']-r['finance_lease_principal'] == D('51.481')
print('Nine sensitivities, both reverse-DCF roots and historical cash bridge reconcile.')
