#!/usr/bin/env python3
import json,re
from decimal import Decimal
from compare import ROOT,equal,effects
def audit():
 out={}
 for lane in ('B','C'):
  d=ROOT/'private-evidence'/lane;f=json.loads((d/'fixture-journal.json').read_text());assert f['committed'] and len(f['dml'])==3;assert len(f['dml'][0]['set'])==1 and f['dml'][0]['set']=={'is_delete':0}
  before=f['before'];after=f['after'];gid=f['owned']['terminal']['goods'];expected=__import__('copy').deepcopy(before)
  for row in expected['goods']:
   if int(row['goods_id'])==gid:row['is_delete']=0 if lane=='C' else '0'
  for t in before:
   if t not in ('goods_sku','goods_image'):equal(expected[t],after[t],lane+'.preparation_scope.'+t)
  for record in f['dml'][1:]:
   table=record['table'];r=after[table];assert len(r)==1 and int(r[0]['id'])==record['generated_PK'] and int(r[0]['goods_id'])==gid and int(r[0]['store_id'])==2147001112;assert set(r[0])==set(record['values'])|{'id'}
   for k,v in record['values'].items():
    if type(v) is int:assert int(r[0][k])==v
    elif type(v) is float:assert float(r[0][k])==v
    elif k in ('goods_price','line_price'):assert Decimal(str(r[0][k]))==Decimal(v)==0
    else:equal(r[0][k],v,lane+'.prepare_value.'+table+'.'+k)
  equal(f['before_protect'],f['after_protect'],lane+'.preparation_natural_default')
  cases={c['scenario']:c for p in d.glob('cases-*.json') for c in json.loads(p.read_text())};wires={w['scenario']:w for w in map(json.loads,(d/'private-wire.jsonl').read_text().splitlines())};counts={'HTTP':len(wires),'INSERT':0,'UPDATE':0,'DELETE':0,'DDL':0,'read_phase_DML':0,'SELECT':0,'metadata_session':0,'independent_after_original_table_sets':20*len(wires),'independent_before_original_table_sets':20*len(wires),'preparation_INSERT':2,'preparation_UPDATE':1+(lane=='B')};seen={}
  for w in wires.values():effects(w,cases[w['scenario']])
  for line in (d/'private-sql.jsonl').read_text().splitlines():
   r=json.loads(line);sql=r['sql'];s=r['scenario'];c=cases[s];assert not re.match(r'^\s*(alter|drop|create|truncate|grant|revoke|delete|merge|replace)\b',sql,re.I)
   m=re.match(r'^\s*(insert|update)\b',sql,re.I)
   if m:
    op=m[1].upper();counts[op]+=1;seen[s]=seen.get(s,0)+1;assert c['method']=='POST' and re.search(r'\byoshop_printer\b',sql,re.I)
    tenant=2147001111 if c['module']=='store' else 2147001112
    if op=='UPDATE':
     assert re.search(r'\bWHERE\b',sql,re.I) and re.search(r'store_id[`"\s]*=\s*[\'\"]?'+str(tenant)+r'\b',sql,re.I) and re.search(r'printer_id[`"\s]*=\s*'+str(c['params']['printerId'])+r'\b',sql,re.I)
    else:assert str(tenant) in sql and c['form']['printer_name'] 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['SELECT']+=1
   else:counts['metadata_session']+=1
  assert counts['INSERT']==2 and counts['UPDATE']==4 and len(seen)==6 and set(seen.values())=={1}
  final=json.loads((d/'final-original.json').read_text());assert len(final['original']['printer'])==2 and all(int(r['is_delete'])==1 and int(r['print_times'])==0 for r in final['original']['printer']);equal(final['protect'],f['before_protect'],lane+'.final_natural_default')
  for t in after:
   if t!='printer':equal(final['original'][t],after[t],lane+'.final_old_own_scope.'+t)
  if lane=='B':
   rec=json.loads((d/'recovery-journal.json').read_text());assert rec['committed'];exp=__import__('copy').deepcopy(rec['before']);
   for row in exp['printer']:
    if int(row['store_id'])==2147001112:row.update(rec['new_values'])
   equal(exp,rec['after'],'B.recovery_three_columns_exact')
  out[lane]=counts
 return out
if __name__=='__main__':
 r=audit();(ROOT/'sql-audit.json').write_text(json.dumps(r,indent=2)+'\n');print(json.dumps(r))
