"""Independent check: Decimal arithmetic + brute-force peak/trough search.
Does not import analyze.py. Run after analyze.py using Python >=3.11.
"""
from pathlib import Path
import csv,io,json,hashlib,math
from decimal import Decimal,getcontext
getcontext().prec=50
B=Path(__file__).resolve().parent
M=json.loads((B/'metrics.json').read_text(encoding='utf8'))
raw=(B/'ecb-eurusd-2016-2025-raw.csv').read_bytes()
assert hashlib.sha256(raw).hexdigest()==M['raw_sha256']
rows=list(csv.DictReader(io.StringIO(raw.decode('utf-8-sig'))))
assert len({r['TIME_PERIOD'] for r in rows})==len(rows)
checks=[];maxerror=0
for result in M['periods']:
    label=result['period'];start,end=label.split('-');subset=[r for r in rows if int(start)<=int(r['TIME_PERIOD'][:4])<=int(end)]
    vals=[Decimal(r['OBS_VALUE']) for r in subset];simple=[100*(b/a-1) for a,b in zip(vals,vals[1:])];logs=[100*(b/a).ln() for a,b in zip(vals,vals[1:])]
    assert result['changes']==len(vals)-1
    assert result['observations']==len(vals)
    for name,seq in [('simple',simple),('log',logs)]:
        n=Decimal(len(seq));mean=sum(seq)/n;ss=sum((x-mean)**2 for x in seq)
        expected={'mean_pct':mean,'population_stdev_pct':(ss/n).sqrt(),'sample_stdev_pct':(ss/(n-1)).sqrt(),'mean_absolute_pct':sum(abs(x) for x in seq)/n,'min_pct':min(seq),'max_pct':max(seq)}
        for field,value in expected.items():
            err=abs(float(value)-result[name][field]);maxerror=max(maxerror,err);assert err<1e-11,(label,name,field,err)
        sorted_values=sorted(seq)
        for p,value in result[name]['quantiles_pct'].items():
            position=Decimal(len(seq)-1)*Decimal(p);lo=int(position);hi=min(lo+1,len(seq)-1);q=sorted_values[lo]+(sorted_values[hi]-sorted_values[lo])*(position-lo)
            err=abs(float(q)-value);maxerror=max(maxerror,err);assert err<1e-11
    for field,idx in [('minimum_change_observation',simple.index(min(simple))+1),('maximum_change_observation',simple.index(max(simple))+1)]:
        assert result[field]['date']==subset[idx]['TIME_PERIOD']
        assert result[field]['previous_date']==subset[idx-1]['TIME_PERIOD']
        assert abs(result[field]['rate_usd_per_eur']-float(vals[idx]))<1e-12
        assert abs(result[field]['previous_rate_usd_per_eur']-float(vals[idx-1]))<1e-12
    assert sum(abs(x)>1 for x in simple)==result['simple_absolute_gt_1pct_count']
    assert sum(x==0 for x in simple)==result['unchanged_rate_count']
    # Enumerate every earlier peak candidate independently of the running-peak code.
    maxdd=Decimal(0);bi=bj=0
    for i,pv in enumerate(vals):
        tv=min(vals[i:]);j=vals.index(tv,i);dd=100*(1-tv/pv)
        if dd>maxdd:maxdd=dd;bi,bj=i,j
    assert abs(float(maxdd)-result['max_drawdown_reference_rate']['maximum_decline_pct'])<1e-11
    assert subset[bi]['TIME_PERIOD']==result['max_drawdown_reference_rate']['peak_date']
    assert subset[bj]['TIME_PERIOD']==result['max_drawdown_reference_rate']['trough_date']
    assert abs(float(sum(logs))-100*math.log(float(vals[-1]/vals[0])))<1e-10
    product=Decimal(1)
    for x in simple:product*=1+x/100
    assert abs(product-vals[-1]/vals[0])<Decimal('1e-40')
    bins=result['log_histogram'];counted=0
    for bb in bins:
        lo=Decimal('-Infinity') if bb['lower'] is None else Decimal(str(bb['lower']));hi=Decimal('Infinity') if bb['upper'] is None else Decimal(str(bb['upper']))
        count=sum(lo<=x<hi for x in logs);assert count==bb['count'];counted+=count
    assert counted==len(logs)
    assert abs(result['simple']['sample_stdev_pct']/result['simple']['population_stdev_pct']-math.sqrt(len(simple)/(len(simple)-1)))<1e-12
    checks.append({'period':label,'decimal_distribution_checks':'PASS','brute_force_drawdown':'PASS','histogram_counts':'PASS','telescoping_log_sum':'PASS','simple_change_product':'PASS','observations':len(vals),'changes':len(simple)})
assert M['periods'][2]['changes']==M['periods'][0]['changes']+M['periods'][1]['changes']+1
R={'status':'PASS','method':'50-digit Decimal calculation; no analyze.py import; exhaustive earlier-peak drawdown comparison; telescoping identities and bin-count checks','maximum_distribution_error_percentage_points':maxerror,'raw_sha256':hashlib.sha256(raw).hexdigest(),'checks':checks}
(B/'independent-verification.json').write_text(json.dumps(R,indent=2)+'\n',encoding='utf8');print(json.dumps(R,indent=2))
