import hashlib, json, subprocess, sys

def digest(x):
    return hashlib.sha256(json.dumps(x,sort_keys=True,separators=(',',':')).encode()).hexdigest()

def validate(r, expected_target, now=100):
    gates=[]
    if r.get('target_surface') != expected_target:
        gates.append('TARGET_MISMATCH')
    if 'raw_preimage' not in r or not r['raw_preimage']:
        gates.append('UNPROBED')
    else:
        if r.get('surface_fingerprint') != digest(r['raw_preimage']): gates.append('SURFACE_CHANGED')
    if now-r.get('as_of',0)>10: gates.append('RECEIPT_STALE')
    return {'status':'ACCEPT' if not gates else 'REFUSE','gates':gates}

def fixture(target, raw, as_of=100):
    return {'target_surface':target,'raw_preimage':raw,'surface_fingerprint':digest(raw) if raw else None,'as_of':as_of}

cases={
 'matching':(fixture('inbox:mentions',{'ids':[1,2]}), 'inbox:mentions',100, {'status':'ACCEPT','gates':[]}),
 'wrong_target':(fixture('inbox:replies',{'ids':[1,2]}), 'inbox:mentions',100, {'status':'REFUSE','gates':['TARGET_MISMATCH']}),
 'unprobed':(fixture('inbox:mentions',None), 'inbox:mentions',100, {'status':'REFUSE','gates':['UNPROBED']}),
 'stale':(fixture('inbox:mentions',{'ids':[1,2]},80), 'inbox:mentions',100, {'status':'REFUSE','gates':['RECEIPT_STALE']}),
}
outputs={}
for name,(r,t,now,expected) in cases.items():
    a=validate(r,t,now); b=validate(r,t,now)
    assert a==expected,(name,a,expected)
    assert a==b,(name,'nondeterministic')
    outputs[name]=a
print(json.dumps(outputs,sort_keys=True,separators=(',',':')))
