import argparse, copy, hashlib, json, re
from pathlib import Path

parser=argparse.ArgumentParser()
parser.add_argument('--native-date',action='store_true')
parser.add_argument('--suffix',default='')
args=parser.parse_args()
root=Path(__file__).resolve().parent/'private-evidence'
checks=[]
def check(ok,label): checks.append({'label':label,'passed':bool(ok)})
def typed(row):
    row=copy.deepcopy(row)
    for k in ('id','number','status','is_del','order_no','del_flag'):
        if k in row: row[k]=int(row[k])
    if not args.native_date and isinstance(row.get('create_time'),str):
        row['create_time']=re.sub(r'\.0{1,6}$','',row['create_time'])
    return row
def expected(label,src,params):
    if label=='setLists':
        rows=[typed(r) for r in src['sets_page_order']]
        time_names={r['uuid']:r['name'] for r in src['times']}
        for row in rows:
            row['delete_able']=int(src['references']['set:'+row['uuid']]==0)
            row['take_time']=','.join(time_names[u] for u in row['use_time'].split(',') if u in time_names)
        return {'code':0,'message':'请求成功','data':{'rows':rows,'total':sum(int(r['is_del'])==1 for r in src['sets'])}}
    if label=='setAll': return {'code':0,'message':'请求成功','data':src['set_all_order']}
    if label=='timeLists':
        rows=[typed(r) for r in src['times_page_order']]
        for row in rows: row['delete_able']=int(src['references']['time-nutrition:'+row['uuid']]==0 and src['references']['time-set:'+row['uuid']]==0)
        return {'code':0,'message':'请求成功','data':{'rows':rows,'total':sum(int(r['del_flag'])==0 for r in src['times'])}}
    table='sets' if label=='setInfo' else 'times'
    return {'code':0,'message':'信息获取成功' if label=='setInfo' else '数据获取成功','data':typed(next(r for r in src[table] if r['uuid']==params['uuid']))}
def strict_equal(a,b):
    if type(a) is not type(b): return False
    if isinstance(a,dict): return a.keys()==b.keys() and all(strict_equal(a[k],b[k]) for k in a)
    if isinstance(a,list): return len(a)==len(b) and all(strict_equal(x,y) for x,y in zip(a,b))
    return a==b
for lane in ('B','C'):
    folder=root/(lane+'-http'+args.suffix)
    wire=[json.loads(line) for line in (folder/('private-retest-wire.jsonl' if args.suffix else 'private-wire.jsonl')).read_text().splitlines()]
    source=json.loads((folder/'private-http-baseline.json').read_text())
    check(len(wire)==(4 if args.suffix else 5),lane+':actual HTTP count')
    check(source==json.loads((folder/('private-retest-final-source.json' if args.suffix else 'private-final-source.json')).read_text()),lane+':final full source unchanged')
    for record in wire:
        label=record['label'];body=record['body'];parsed=json.loads(body)
        check(record['status']==200 and parsed['code']==0,lane+':'+label+':status/business')
        check(hashlib.sha256(body.encode()).hexdigest()==record['body_sha256'],lane+':'+label+':raw SHA')
        check(record['source_before']==source==record['source_after'],lane+':'+label+':all columns+actor+references unchanged')
        check(strict_equal(parsed,expected(label,source,record['params'])),lane+':'+label+':full body/types/order/source')
        check(bool(parsed['data'].get('rows',parsed['data'])) if isinstance(parsed['data'],dict) else bool(parsed['data']),lane+':'+label+':nonempty')
        sql=record['prepared_SQL']
        check(bool(sql),lane+':'+label+':actual DB SQL nonempty')
        check(all(re.match(r'^\s*(SELECT|SHOW|EXPLAIN)\b',q['queryString'],re.I) or q['queryString'].strip()=='CALL SP_TABLEDEF(?, ?)' for q in sql),lane+':'+label+':native read-only SQL')
        check(all(q.get('ok') is True and 'error' not in q for q in sql),lane+':'+label+':all native prepared execution succeeded')
        if args.suffix:
            cls='app\\p\\logic\\NutritionTime' if label.startswith('time') else 'app\\p\\logic\\Nutrition'
            sha='40da145b0fff9daa733872e6ffb3eeb9958de55ca66f6d87336efce8d2461c04' if label.startswith('time') else '824b19d4ca6a3d3eced4c228edb88c4bdab081477897472b3a753b01bf12765f'
            check(record['reflection'][cls]['sha256']==sha,lane+':'+label+':actual Reflection Root SHA')
            original=json.loads((root/(lane+'-http')/('private-'+label+'.httpbody')).read_text())
            check(strict_equal(parsed,original) if lane=='B' else not strict_equal(parsed,original),lane+':'+label+':B original unchanged / C repaired')
            if lane=='B': check(body==(root/'B-http'/('private-'+label+'.httpbody')).read_text(),lane+':'+label+':B raw bytes unchanged')
result={'passed':all(c['passed'] for c in checks),'mode':'native date source' if args.native_date else 'legacy MySQL seconds contract','assertions':len(checks),'failures':[c['label'] for c in checks if not c['passed']]}
print(json.dumps(result,ensure_ascii=False,indent=2))
raise SystemExit(0 if result['passed'] else 2)
