import json,re
from compare import ROOT,equal
def audit():
 out={}
 for lane in ('B','C'):
  p=ROOT/'private-evidence'/lane;j=json.loads((p/'run-journal.json').read_text());pre=json.loads((p/'preflight.json').read_text());assert j['complete'] and j['own_token_absent'];gid=j['new_goods_id'];cases={c['scenario']:c for c in j['cases']};counts={'HTTP':8,'native_assertions':32,'API_INSERT':0,'API_UPDATE':0,'API_DELETE_statements':0,'API_deleted_original_rows':2,'DDL':0,'preparation_DML':0,'read_DML':0,'business_SELECT':0,'metadata_session':0,'independent_after_original_table_sets':160,'independent_before_original_table_sets':160};per={}
  for line in (p/'private-sql.jsonl').read_text().splitlines():
   r=json.loads(line);s=r['scenario'];sql=r['sql'];c=cases[s];m=re.match(r'^\s*(INSERT|UPDATE|DELETE)\b',sql,re.I);assert not re.match(r'^\s*(ALTER|DROP|CREATE|TRUNCATE|MERGE|REPLACE|GRANT|REVOKE)\b',sql,re.I)
   if m:
    op=m[1].upper();assert c['method']=='POST';table=re.search(r'\byoshop_goods(?:_sku|_image|_spec_rel)?\b',sql,re.I);assert table;table=table[0].lower();per.setdefault(c['stage'],{});per[c['stage']][op]=per[c['stage']].get(op,0)+1;counts['API_'+('DELETE_statements' if op=='DELETE' else op)]+=1
    if op!='INSERT':
     assert re.search(r'\bWHERE\b',sql,re.I) and re.search(r'store_id[`"\s]*=\s*[\'\"]?2147001112\b',sql,re.I) and re.search(r'goods_id[`"\s]*(?:=|IN\s*\()\s*[\'\"]?'+str(gid)+r'\b',sql,re.I)
    else:assert '2147001112' in sql
   elif re.match(r'^\s*SELECT\b',sql,re.I) and not re.search(r'\bSYSOBJECTS\b|\bSYSCOLUMNS\b|USER_TAB_COLUMNS|USER_CONS_COLUMNS|USER_CONSTRAINTS|\bDUAL\b',sql,re.I):counts['business_SELECT']+=1
   else:counts['metadata_session']+=1
  equal(per,{'ADD':{'INSERT':3},'EDIT':{'UPDATE':1,'DELETE':3,'INSERT':2},'STATE_UP':{'UPDATE':1},'STATE_DOWN':{'UPDATE':1},'DELETE':{'UPDATE':1}},lane+'.exact_DML_stages')
  edit_before=j['stages']['READ_ADD']['after'];edit_after=j['stages']['EDIT']['after'];deleted={}
  for t in ('goods_sku','goods_image','goods_spec_rel'):
   old={r['id'] for r in edit_before[t]};new={r['id'] for r in edit_after[t]};deleted[t]=len(old-new)
  equal(deleted,{'goods_sku':1,'goods_image':1,'goods_spec_rel':0},lane+'.actual_own_deleted_rows')
  for stage,s in j['stages'].items():assert s['native_exit']==0 and all(x['failures']==0 for x in s['stats'])
  final=json.loads((p/'final-original.json').read_text());equal(j['after'],final['original'],lane+'.independent_final');equal(pre['protect'],final['protect'],lane+'.natural_default')
  out[lane]={'counts':counts,'DML_by_stage':per,'SQL_evidence_layer':'ThinkPHP Db::listen framework debug interpolation (getRealSql/getLastSql), NOT PDOStatement.queryString or server trace','physical_deleted_rows':deleted}
 return out
if __name__=='__main__':
 r=audit();(ROOT/'sql-audit.json').write_text(json.dumps(r,indent=2)+'\n');print(json.dumps(r))
