import copy,hashlib,json,re
from pathlib import Path
from compare import eq,verify,verify_wire
P=Path(__file__).resolve().parent
def trace_only(raw):
 b=json.loads(raw);assert re.fullmatch('[0-9a-f]{13}',b['trace_id'])
 out,n=re.subn(r'"trace_id":"[0-9a-f]{13}"','"trace_id":"VALID_TRACE"',raw)
 assert n==1
 return out
def id_map(j):
 out={}
 for r in j['before']['user']:out[('user_id',int(r['user_id']))]='PRIOR_USER_'+str(r['store_id'])
 for r in j['before']['upload_file']:out[('file_id',int(r['file_id']))]='PRIOR_FILE_'+str(r['store_id']);out[('avatar_id',int(r['file_id']))]='PRIOR_FILE_'+str(r['store_id'])
 for r in j['owned']:
  label=r['table']+'_'+r['module'];out[(r['pk'],r['id'])]=label
 return out
def mapped(value,m):
 if isinstance(value,list):return [mapped(x,m) for x in value]
 if isinstance(value,dict):
  result={}
  for k,v in value.items():
   if k=='trace_id':assert re.fullmatch('[0-9a-f]{13}',v);result[k]='VALID_TRACE'
   elif type(v) is int and (k,v) in m:result[k]=m[k,v]
   else:result[k]=mapped(v,m)
  return result
 return value
def verify_all():
 original_source=json.loads((P/'source-frozen-sha.json').read_text());final_source=json.loads((P/'source-final-sha.json').read_text());out={'true_HTTP':76,'complete_wire':76,'original':{},'final':{},'B_raw_trace_only_equal':0,'strict_BC_pairs':0,'final_full_original_scopes_unchanged':True,'fixture_retained_each':7}
 assert {k for k in original_source['files'] if original_source['files'][k]!=final_source['files'][k]}==final_source['accepted_changes'].keys()
 fixtures={};maps={}
 for l in 'BC':
  schema=json.loads((P/f'structure-{l}.json').read_text());r=verify(P/'private-evidence'/l,schema,original_source);f=verify(P/'private-evidence'/f'{l}-final',schema,final_source);out['original'][l]=r;out['final'][l]=f
  assert len(r)==27 and sum(x['pass'] for x in r)==(27 if l=='B' else 11)
  assert len(f)==(6 if l=='B' else 16) and all(x['pass'] for x in f)
  fixtures[l]=json.loads((P/'private-evidence'/l/'fixture-journal.json').read_text());maps[l]=id_map(fixtures[l]);assert fixtures[l]['committed'] and len(fixtures[l]['owned'])==7
  cases=json.loads((P/'private-evidence'/l/'cases-NA.json').read_text());assert len(cases)==27
  for wire_path in (P/'private-evidence'/l).glob('wire-PILOT_LF_*.json'):
   wire=json.loads(wire_path.read_text());eq(wire['case'],cases[wire['scenario']],'original frozen full request case')
  end=json.loads((P/'private-evidence'/f'{l}-final'/'final-FINAL-original.json').read_text())['original'];eq(end,fixtures[l]['after'],'complete36 scopes')
  for w in (P/'private-evidence'/f'{l}-final').glob('wire-*.json'):
   wire=json.loads(w.read_text());original=json.loads((P/'private-evidence'/l/(w.name.replace('PILOT_LF_FINAL_','PILOT_LF_'))).read_text());a=copy.deepcopy(wire['case']);a['scenario']=original['case']['scenario'];eq(a,original['case'],'same method/path/query/host/auth/ids');assert (w.parent/('response-'+wire['scenario']+'.body')).read_bytes()==wire['raw'].encode()
 for w in (P/'private-evidence'/'B-final').glob('wire-*.json'):
  b=json.loads(w.read_text());old=json.loads((P/'private-evidence'/'B'/w.name.replace('PILOT_LF_FINAL_','PILOT_LF_')).read_text());assert trace_only(b['raw'])==trace_only(old['raw']);out['B_raw_trace_only_equal']+=1
  c=json.loads((P/'private-evidence'/'C-final'/w.name).read_text());eq(mapped(json.loads(b['raw']),maps['B']),mapped(json.loads(c['raw']),maps['C']),'strict complete BC body');out['strict_BC_pairs']+=1
 assert out['B_raw_trace_only_equal']==out['strict_BC_pairs']==6
 return out
if __name__=='__main__':
 out=verify_all();(P/'comparison-final.json').write_text(json.dumps(out,ensure_ascii=False,indent=2)+'\n');print(json.dumps({k:v for k,v in out.items() if k not in ('original','final')}))
