"""Post-run evidence audit; no constructor or runtime execution.
Run from the flattened public downloads: python3 verify_results.py
Local layout results/ is also accepted. Writes verification.json only.
"""
import collections,csv,hashlib,json,math,pathlib,statistics,time,datetime
ROOT=pathlib.Path(__file__).resolve().parent
DATA=ROOT/'results' if (ROOT/'results').is_dir() else ROOT

def read(name):return json.loads((DATA/name).read_text())
def main():
    cpu=time.process_time();wall=time.perf_counter();history={};targets={};ages={};last={}
    with (DATA/'events.csv').open() as f:
        for e in csv.DictReader(f):
            g,ep,i,a,t=map(int,[e['group'],e['episode'],e['event_id'],e['a'],e['t']]);k=(g,ep)
            bank=history.setdefault(k,[0]*4);written=last.setdefault(k,[None]*4)
            if e['kind']=='W':bank[a]=int(e['v']);written[a]=t
            else:
                targets[g,ep,i]=bank[a];ages[g,ep,i]=t-written[a]
                assert int(e['target'])==bank[a] and int(e['retention_ticks'])==ages[g,ep,i]
    by=collections.defaultdict(list);seen=set();failures=collections.Counter();observed_latencies=[];query_count=0
    with (DATA/'queries.csv').open() as f:
        for r in csv.DictReader(f):
            g,ep,i,t=map(int,[r['group'],r['episode'],r['event_id'],r['input_tick']])
            k=(g,r['setting'],r['arm'],r['condition']);unique=(*k,ep,i)
            assert unique not in seen;seen.add(unique)
            target=targets[g,ep,i];assert int(r['target'])==target and int(r['retention_ticks'])==ages[g,ep,i]
            responses=json.loads(r['responses']);assert all(x[0]==i for x in responses)
            correct=len(responses)==1 and responses[0][2]==target
            success=correct and t+1<=responses[0][1]<=t+44
            if r['validity']=='valid':
                assert int(r['correct'])==correct and int(r['success'])==success
                expected='ok' if success else 'missing' if not responses else 'duplicate' if len(responses)>1 else 'incorrect' if not correct else 'late'
                assert r['failure']==expected
            else:assert int(r['success'])==0
            by[k].append(int(r['success']));failures[r['condition'],r['failure']]+=1;query_count+=1
            if r['condition']=='intact':observed_latencies.extend(x[1]-t for x in responses)
    assert len(by)==576 and query_count==83568
    sums=read('summary.json');rows=sums['rows']
    for r in rows:
        k=(r['group'],r['setting'],r['arm'],r['condition']);vals=by[k]
        assert sum(vals)==r['successes'] and len(vals)==r['queries'] and statistics.mean(vals)==r['fraction']
        expected=sum(k[0]==g for g,ep,i in targets)
        assert len(vals)==expected
    held=sorted({k[1] for k in by if k[1]!='m2-r2-d1'})
    differences=[statistics.mean(statistics.mean(by[g,s,'D','intact'])-statistics.mean(by[g,s,'B','intact']) for s in held) for g in range(12)]
    challenge=collections.defaultdict(list)
    with (DATA/'challenge.csv').open() as f:
        for r in csv.DictReader(f):
            k=(int(r['group']),r['setting'],r['arm'],r['condition'],int(r['pair']));bank=json.loads(r['bank']);a=int(r['address']);t=int(r['input_tick']);target=int(r['target'])
            assert bank[a]==target
            responses=json.loads(r['responses']);ok=len(responses)==1 and responses[0][2]==target and 1<=responses[0][1]-t<=44
            assert int(r['success'])==ok
            challenge[k].append((target,int(r['success'])))
    assert len(challenge)==2304 and all(len(v)==2 and {x[0] for x in v}=={-1,1} for v in challenge.values())
    construction=read('construction.json')
    hashes={(r['group'],r['setting'],r['arm'],r['condition']):r['circuit_sha256'] for r in construction}
    assert all(hashes[g,s,'D',cond]==hashes[g,s,'B',cond] for g,s,a,cond in hashes if a=='D')
    assert all(r['replay_agreement'] for r in rows if r['arm']=='D')
    result=dict(verified_utc=datetime.datetime.now(datetime.timezone.utc).isoformat(),method='content audit and independent reaggregation; no new runtime evaluation',
        per_query_oracle_and_score_recomputed=True,unique_complete_ordinary_rows=query_count,
        paired_query_rows=4608,dependent_pairs=2304,all_pair_targets_opposite=True,
        intact_latency_min=min(observed_latencies),intact_latency_max=max(observed_latencies),
        seed_differences=differences,mean_paired_difference=statistics.mean(differences),
        paired_circuit_hashes_identical=True,D_replayed_episodes=1152,
        failures={('/'.join(k)):v for k,v in sorted(failures.items())},
        input_sha256={n:hashlib.sha256((DATA/n).read_bytes()).hexdigest() for n in ['events.csv','queries.csv','challenge.csv','summary.json','construction.json']},
        cpu_seconds=time.process_time()-cpu,wall_seconds=time.perf_counter()-wall)
    (ROOT/'verification.json').write_text(json.dumps(result,indent=2)+'\n');print(json.dumps(result,indent=2))
if __name__=='__main__':main()
