#!/usr/bin/env python3
import copy,hashlib,importlib.util,json,re
from pathlib import Path
ROOT=Path(__file__).resolve().parent
spec=importlib.util.spec_from_file_location('frozen_order_oracle',ROOT.parent/'parallel-ai-order-recharge-read-20261011/compare.py');base=importlib.util.module_from_spec(spec);spec.loader.exec_module(base)
base.META=json.loads((ROOT/'structure-B.json').read_text())['tables'];equal=base.equal

def file(row,module,lane,phase):
 d=base.cast(row,'upload_file',lane,phase);url=f'http://{module}.order-related.invalid/uploads/{row["file_path"]}';d['preview_url']=d['external_url']=url;return d
base.file=file
def pick(original,table,key,value):
 rows=[r for r in original[table] if int(r[key])==int(value)];assert len(rows)==1,(table,key,value);return rows[0]
def order_row(row,original,module,lane,phase,relations=False):
 d=base.cast(row,'order',lane,phase);d['order_price']=base.money(row['order_price']);d['update_price']={'symbol':'-' if float(row['update_price'])<0 else '+','value':base.money(abs(float(row['update_price'])))}
 for k in ('pay_time','delivery_time','receipt_time'):d[k]=base.date(row[k]) if int(row[k]) else ''
 d['order_source_data']=json.loads(row['order_source_data']) or [];d['state_text']='已取消';assert int(row['order_status'])==20
 if relations:d['user']=base.user(pick(original,'user','user_id',row['user_id']),original,module,lane,phase,False);d['address']=None;assert not original['order_address']
 return d
def order_goods(row,original,module,lane,phase,content=False):
 d=base.goods(row,original,module,lane,phase)
 if content:d['content']=row['content']
 return d
def delivery(row,o,module,lane,phase,detail):
 d=base.cast(row,'order_delivery',lane,phase)
 if detail:return d
 d.pop('eorder_html');d['orderData']=order_row(pick(o,'order','order_id',row['order_id']),o,module,lane,phase,True);d['goods']=[];d['express']=None;assert not o['express']
 for r in o['order_delivery_goods']:
  if int(r['delivery_id'])!=int(row['delivery_id']):continue
  item=base.cast(r,'order_delivery_goods',lane,phase);item['goods']=order_goods(pick(o,'order_goods','order_goods_id',r['order_goods_id']),o,module,lane,phase,True);d['goods'].append(item)
 return d
def refund(row,o,module,lane,phase,detail):
 d=base.cast(row,'order_refund',lane,phase);d['send_time']=base.date(row['send_time']) if int(row['send_time']) else '';order=pick(o,'order','order_id',row['order_id']);d['orderData']=order_row(order,o,module,lane,phase);d['orderGoods']=order_goods(pick(o,'order_goods','order_goods_id',row['order_goods_id']),o,module,lane,phase);d['user']=base.user(pick(o,'user','user_id',row['user_id']),o,module,lane,phase,not detail)
 if detail:
  d['images']=[];d['express']=None;d['address']=None;assert not o['express'] and not o['order_refund_address']
  for r in o['order_refund_image']:
   if int(r['order_refund_id'])!=int(row['order_refund_id']):continue
   im=base.cast(r,'order_refund_image',lane,phase);f=file(pick(o,'upload_file','file_id',r['image_id']),module,lane,phase);im['file']=f;im['image_url']=f['preview_url'];d['images'].append(im)
 else:d['order_no']=order['order_no']
 return d
def expected_data(w,c,lane,phase):
 o=w['original'];module=c['module'];tenant=2147001111 if module=='store' else 2147001112;is_delivery='delivery' in c['path'];detail=c['path'].endswith('/detail');table='order_delivery' if is_delivery else 'order_refund';pk='delivery_id' if is_delivery else 'order_refund_id';params=c['params'] or {};rows=[r for r in o[table] if int(r['store_id'])==tenant]
 if detail:
  target=params['deliveryId' if is_delivery else 'orderRefundId'];rows=[r for r in rows if int(r[pk])==target];assert len(rows)==1;data=delivery(rows[0],o,module,lane,phase,True) if is_delivery else refund(rows[0],o,module,lane,phase,True);return {'detail':data}
 assert not params;rows.sort(key=lambda r:(-int(r['create_time']),int(r[pk])));count=len(rows);return {'list':{'total':count,'per_page':10,'current_page':1,'last_page':(count+9)//10,'data':[(delivery(r,o,module,lane,phase,False) if is_delivery else refund(r,o,module,lane,phase,False)) for r in rows[:10]]}}

def normalize(b,fixture):
 d=copy.deepcopy(b);d['trace_id']='VALIDATED_TRACE';maps={k:{} for k in ('order_id','user_id','goods_id','order_goods_id','file_id','image_id','avatar_id','delivery_id','order_refund_id')};by_tenant={}
 for module,ids in fixture['owned'].items():
  by_tenant[2147001111 if module=='store' else 2147001112]=module
  for t,k in [('order','order_id'),('user','user_id'),('goods','goods_id'),('order_goods','order_goods_id'),('upload_file','file_id'),('order_delivery','delivery_id'),('order_refund','order_refund_id')]:maps[k][ids[t]]=module+'.'+t
  maps['image_id'][ids['upload_file']]=module+'.upload_file';maps['avatar_id'][ids['upload_file']]=module+'.upload_file'
 def walk(v,path='$'):
  if isinstance(v,dict):
   for k,x in v.items():
    if k=='id' and type(x) is int and ('images[' in path or 'goods[' in path):
     table='order_refund_image' if 'images[' in path else 'order_delivery_goods';module=by_tenant[v['store_id']];assert x==fixture['owned'][module][table];v[k]=module+'.'+table
    elif k in maps and type(x) is int and x in maps[k]:v[k]=maps[k][x]
    else:walk(x,path+'.'+k)
  elif isinstance(v,list):
   for i,x in enumerate(v):walk(x,path+f'[{i}]')
 walk(d);return d

def verify():
 body_map={};normalized={};results={};count=0;positive=0
 for lane in ('B','C'):
  d=ROOT/'private-evidence'/lane;f=json.loads((d/'fixture-journal.json').read_text());cases={c['scenario']:c for path in d.glob('cases-*.json') for c in json.loads(path.read_text())};out=[]
  for line in (d/'private-wire.jsonl').read_text().splitlines():
   w=json.loads(line);s=w['scenario'];c=cases[s];phase=s.split('_')[2];b=json.loads(w['raw']);count+=1;assert w['http_status']==200 and set(b)=={'status','message','data','trace_id'} and type(b['status']) is int and re.fullmatch('[0-9a-f]{13}',b['trace_id'])
   historic=lane=='C' and phase=='NA' and c['name'].endswith('_LIST')
   if historic:assert b['status']==500 and '-2007' in b['message'] and '[order]' in b['message']
   else:
    assert b['status']==c['expected_status'],s
    if b['status']==200:equal(b['data'],expected_data(w,c,lane,phase),s+'.full_original_projection');positive+=1
    else:equal(b['data'],[],s+'.error_data')
    normalized[(lane,s)]=normalize(b,f)
   equal(w['original'],f['after'],s+'.own13tables_unchanged');body_map[(lane,s)]=b;out.append({'scenario':s,'status':b['status'],'historical_sql_red':historic,'full_original_projection_equal':not historic and b['status']==200,'raw_sha256':hashlib.sha256(w['raw'].encode()).hexdigest()})
   if phase=='FINAL':
    hashes={'app/common/model/Order.php':'a09c9ed5c963a56172d1815b81646de7ff8bef8f5a4b312dc8f62089775828ce','app/common/database/DmBuilder.php':'58e1e79ce69881cc305c6fd33adec0e9a3d030ac15b4c00ae464cbaa4cce2b59','cores/BaseModel.php':'15b09472d9152906bd3f6cfa6b98ea87b1952abcc9587e7e72526fff73ab78c6'}
    for path,candidate in [('app/store/model/order/Delivery.php','storeDeliveryCandidate.php'),('app/terminal/model/order/Delivery.php','terminalDeliveryCandidate.php'),('app/store/model/OrderRefund.php','storeRefundCandidate.php'),('app/terminal/model/OrderRefund.php','terminalRefundCandidate.php'),('app/store/controller/order/Delivery.php','storeDeliveryControllerCandidate.php'),('app/terminal/controller/order/Delivery.php','terminalDeliveryControllerCandidate.php'),('app/store/controller/order/Refund.php','storeRefundControllerCandidate.php'),('app/terminal/controller/order/Refund.php','terminalRefundControllerCandidate.php'),('app/common/service/OrderReadResponse.php','OrderReadResponseRelatedCandidate.php')]:hashes[path]=hashlib.sha256((ROOT/candidate).read_bytes()).hexdigest()
    equal(w['source_sha256'],hashes,s+'.actual_final_source_identity')
  results[lane]=out
 pairs=[];unchanged=[]
 for module in ('STORE','TERMINAL'):
  for name in ('DELIVERY_LIST','REFUND_LIST','REFUND_DETAIL','DELIVERY_DETAIL'):
   phase='NA' if name=='DELIVERY_DETAIL' else 'FINAL';key=f'PILOT_RD_{phase}_{module}_{name}';equal(normalized[('B',key)],normalized[('C',key)],key+'.whole_BC_body');pairs.append(key)
   if name=='DELIVERY_DETAIL':continue
   oldphase='NA' if name=='REFUND_DETAIL' else 'GREEN';old=f'PILOT_RD_{oldphase}_{module}_{name}';a=copy.deepcopy(body_map[('B',old)]);b=copy.deepcopy(body_map[('B',key)]);a['trace_id']=b['trace_id']='VALIDATED_TRACE';equal(a,b,key+'.B_full_body_control');unchanged.append(key)
 return {'HTTP':count,'positive_original_projections':positive,'complete_BC_positive_pairs':pairs,'final_B_unchanged':unchanged,'original_C_SQL_reds':4,'cases':results}

if __name__=='__main__':
 r=verify();(ROOT/'comparison.json').write_text(json.dumps(r,ensure_ascii=False,indent=2)+'\n');print(json.dumps({k:v for k,v in r.items() if k!='cases'},ensure_ascii=False))
