import copy,datetime,hashlib,json
from pathlib import Path
p=Path(__file__).parent
read=lambda f:json.loads(Path(f).read_text())
b=read('/private/tmp/cdx-category-read-bodies-B.json');c=read('/private/tmp/cdx-category-evidence-C/private-read-bodies.json')
audits={x:read(p/f'independent-audit-{x}.json') for x in 'BC'}
def own(row,lane,dates=False):
    row=copy.deepcopy(row);a=audits[lane]['retained'];assert row['id']==a['id'] and row['name'].startswith(a['marker'])
    row['id']='<source-owned-id>';row['name']='<source-owned-marker>'+row['name'][len(a['marker']):]
    if dates:
        for field in ('create_time','update_time'):
            assert type(row[field]) is str and len(row[field])==19
            assert datetime.datetime.strptime(row[field],'%Y-%m-%d %H:%M:%S').strftime('%Y-%m-%d %H:%M:%S')==row[field]
            assert audits[lane]['checks']['owned_raw_seconds_zero_fraction']
            row[field]='<source-validated-second-time>'
    return row
def digest(v):return hashlib.sha256(json.dumps(v,ensure_ascii=False,separators=(',',':'),sort_keys=True).encode()).hexdigest()
cases=[]
for name in ('own_list_seconds','formal_delete_after_read'):
    pair=[]
    for lane,body in [('B',b),('C',c)]:
        v=copy.deepcopy(body[name])
        if name=='own_list_seconds':assert len(v['data']['rows'])==1;v['data']['rows']=[own(v['data']['rows'][0],lane,True)]
        pair.append(v)
    assert pair[0]==pair[1] and digest(pair[0])==digest(pair[1]);cases.append({'scenario':name,'scope':'complete-wire-values-types-and-order','sha256':digest(pair[0]),'passed':True})
for name in ('options_form','options_include','options_filter'):
    pair=[]
    for lane,body in [('B',b),('C',c)]:
        a=audits[lane]['retained'];rows=[r for r in body[name]['data'] if r['id']==a['id']]
        assert len(rows)==(0 if name=='options_form' else 1)
        pair.append([own(r,lane) for r in rows])
        green=read(p/f'read-green-{lane}.json');assert green['cases'][name]['complete_rows_source_equal']
    assert pair[0]==pair[1] and digest(pair[0])==digest(pair[1]);cases.append({'scenario':name,'scope':'owned-projection-parity-plus-each-complete-original-source-not-cross-snapshot-full-equality','sha256':digest(pair[0]),'passed':True})
print(json.dumps({'passed':True,'complete_wire_cases':2,'source_and_owned_projection_cases':3,'natural_list':'observed-only-extra-no-cross-snapshot-equality-claim','mapping':['source-owned-ID','source-owned-marker-prefix-only','source-validated-second-date-for-own-list-only'],'cases':cases},indent=2))
