<?php
declare(strict_types=1);date_default_timezone_set('Asia/Shanghai');define('CDX_CATEGORY_CONTEXT',true);require __DIR__.'/preflight.php';
$mode=$argv[1]??'frozen';$old=json_decode((string)file_get_contents(__DIR__.'/private-crud.json'),true);$owned=$old['retained'];$id=$owned['id'];$marker=$owned['marker'];$naturalBefore=$hashRows('SELECT * FROM '.$p.'dishes_custom_category WHERE ID<>? ORDER BY ID',[$id]);$out=['lane'=>$lane,'mode'=>$mode,'failure'=>null,'cases'=>[],'fixture_dml'=>0,'business_dml'=>0];$bodies=[];$hash=static function($x):string{return hash('sha256',serialize($x));};
$admin=$q('SELECT ID,UUID FROM '.$p.'user WHERE ID=(SELECT MIN(ID) FROM '.$p.'user WHERE TYPE=0 AND IS_DELETE=0)')[0];require_once $root.'/application/base/Security.php';$token=\app\base\Security::encrypt(implode("\t",[(string)$admin['id'],(string)$admin['uuid'],'CDXCAT10ADMIN','0','','','CDXCAT10ADMIN']));
$rq=static function(string $label,string $action,array $params)use($lane,$token,&$out,&$bodies,$check):array{$path='/p/dishCustomCategory/'.$action;$raw=(string)file_get_contents('http://127.0.0.1:'.($lane==='B'?18301:18302).$path,false,stream_context_create(['http'=>['method'=>'POST','header'=>'token: '.$token."\r\nContent-Type: application/x-www-form-urlencoded\r\n",'content'=>http_build_query($params),'ignore_errors'=>true,'timeout'=>30]]));$body=json_decode($raw,true);$bodies[$label]=json_decode($raw);$out['cases'][$label]=['method'=>'POST','path'=>$path,'raw_wire_sha256'=>hash('sha256',$raw),'code'=>$body['code']??null];$check(($body['code']??null)===0,'Read success');return $body;};
try{
 if($mode==='restore-read-delete'){$row=$q('SELECT * FROM '.$p.'dishes_custom_category WHERE ID=?',[$id])[0];$check(strpos($row['name'],$marker)===0&&$row['create_by']==='CDXCAT10ADMIN'&&(int)$row['status']===2&&(int)$row['is_delete']===1,'Exact old owned soft row');$check((int)$q('SELECT COUNT(*) AS N FROM '.$p.'dishes WHERE CUSTOM_CATEGORY_ID=?',[$id])[0]['n']===0,'No unknown refs');$db->prepare('UPDATE '.$p.'dishes_custom_category SET IS_DELETE=0 WHERE ID=? AND NAME=? AND STATUS=2 AND IS_DELETE=1')->execute([$id,$row['name']]);$out['fixture_dml']=1;
  $raw=$q('SELECT * FROM '.$p.'dishes_custom_category WHERE ID=?',[$id])[0];$body=$rq('own_list_seconds','list',['keyword'=>$marker,'page_size'=>100]);$check(count($body['data']['rows'])===1,'Own list');$actual=$body['data']['rows'][0];foreach(['id','code','name','status','is_system','is_delete','create_by','create_time','update_time']as $key){$expected=$raw[$key];if(in_array($key,['id','status','is_system','is_delete'],true))$expected=(int)$expected;if(in_array($key,['create_time','update_time'],true)){$check(preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.0{1,6})?$/D',$expected)===1,'Source seconds only zero fraction');$expected=substr($expected,0,19);}$check(array_key_exists($key,$actual)&&$actual[$key]===$expected,'Formal source field '.$key);}$check($actual['dish_count']===0,'Own count zero');$out['cases']['own_list_seconds']['all_formal_fields_types_source_equal']=true;$out['cases']['own_list_seconds']['create_time_length']=strlen($actual['create_time']);$out['cases']['own_list_seconds']['update_time_length']=strlen($actual['update_time']);
 }
 foreach(['form'=>['usage'=>'form'],'include'=>['usage'=>'form','include_id'=>$id],'filter'=>['usage'=>'filter']]as $label=>$params){$body=$rq('options_'.$label,'options',$params);$where='IS_DELETE=0'.($label==='filter'?'':($label==='include'?' AND (STATUS=1 OR ID=?)':' AND STATUS=1'));$args=$label==='include'?[$id]:[];$rows=$q('SELECT ID,CODE,NAME,STATUS,IS_SYSTEM FROM '.$p.'dishes_custom_category WHERE '.$where.' ORDER BY IS_SYSTEM ASC,ID ASC',$args);foreach($rows as &$r){foreach(['id','status','is_system']as $k)$r[$k]=(int)$r[$k];}unset($r);$check($body['data']===$rows,'Complete options source values/types/order');$out['cases']['options_'.$label]['complete_rows_source_equal']=true;$out['cases']['options_'.$label]['source_rows']=count($rows);}
 $body=$rq('natural_list','list',['page'=>1,'page_size'=>100]);$out['cases']['natural_list']['rows']=count($body['data']['rows']);
}catch(Throwable $e){$out['failure']=['class'=>get_class($e),'reason'=>$e->getMessage()];}
finally{if($out['fixture_dml']){try{$rq('formal_delete_after_read','delete',['id'=>$id]);$out['business_dml']=1;}catch(Throwable $e){$out['cleanup_failure']=get_class($e);}}$out['retained']=$q('SELECT ID,STATUS,IS_DELETE FROM '.$p.'dishes_custom_category WHERE ID=?',[$id])[0];$out['natural_category_unchanged']=$hashRows('SELECT * FROM '.$p.'dishes_custom_category WHERE ID<>? ORDER BY ID',[$id])===$naturalBefore;$out['dishes_projection_unchanged']=$hashRows('SELECT ID,UUID,CUSTOM_CATEGORY_ID,IS_DELETE,IS_DEL FROM '.$p.'dishes ORDER BY ID')===$report['dishes_source'];foreach(['private-read-regression.json'=>$out,'private-read-bodies.json'=>$bodies]as $f=>$v){file_put_contents(__DIR__.'/'.$f,json_encode($v,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE));chmod(__DIR__.'/'.$f,0600);}}
echo json_encode($out),"\n";exit($out['failure']?2:0);
