<?php
declare(strict_types=1);define('CDX_GRADE_CONTEXT',true);require __DIR__.'/preflight.php';$lease=json_decode(file_get_contents(__DIR__.'/private-lease.json'),true);$own=json_decode(file_get_contents(__DIR__.'/private-own.json'),true);$baseline=json_decode(file_get_contents(__DIR__.'/private-baseline.json'),true);$original=json_decode(file_get_contents(__DIR__.'/private-crud.json'),true);$out=['lane'=>$lane,'cases'=>[],'failure'=>null,'source_checks'=>[],'business_dml'=>0,'fixture_dml'=>0];$bodies=[];$originalHashes=[];foreach($original['cases']as $case)$originalHashes[$case['scenario']]=$case['raw_wire_sha256'];
$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'],'CDXGR10ADMIN','0','','','CDXGR10ADMIN']));
$rq=static function(string $module,string $label,string $action,array $params,int $expected)use($lane,$token,&$out,&$bodies,$check):array{$path='/p/'.$module.'/'.$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[$module.'.'.$label]=json_decode($raw);$out['cases'][]=['scenario'=>$module.'.'.$label,'method'=>'POST','path'=>$path,'code'=>$body['code']??null,'raw_wire_sha256'=>hash('sha256',$raw)];$check(($body['code']??null)===$expected,'Unexpected result '.$label);return $body;};
try{foreach($own as $module=>$self){$rows=$q('SELECT * FROM '.$p.$self['table'].' WHERE UUID=?',[$self['uuid']]);$check(count($rows)===1&&strpos($rows[0][$self['marker_field']],$self['marker'])===0&&$rows[0]['staff_uuid']===$lease['staff']['uuid'],'Exact self row');$row=$rows[0];$check($row['create_by']===mb_substr($admin['uuid'],0,32,'UTF-8'),'Original operator source32 not short actor');$body=$rq($module,'info_green','info',['uuid'=>$self['uuid']],0);$expected=$row;$expected['id']=(int)$expected['id'];$check(preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.0{1,6})?$/D',$expected['create_time'])===1,'Actual stored seconds/zero fraction');$expected['create_time']=substr($expected['create_time'],0,19);$check($body['data']===$expected,'All detail fields/types source');$i=count($out['cases'])-1;$out['cases'][$i]['all_original_fields_types_source_equal']=true;$out['cases'][$i]['create_time_length']=strlen($body['data']['create_time']);$out['source_checks'][$module]=['original_operator_36'=>strlen($admin['uuid'])===36,'create_by_source32_prefix_verified'=>true,'raw_create_time_zero_fraction'=>true];if($lane==='B')$check($out['cases'][$i]['raw_wire_sha256']===$originalHashes[$module.'.info_updated'],'B same owned record full original wire unchanged');$out['cases'][$i]['B_original_same_input_wire_unchanged']=$lane==='B'?true:null;
 $body=$rq($module,'lists_green','lists',['staff_uuid'=>$lease['staff']['uuid'],'page'=>1],0);$matching=array_values(array_filter($body['data']['rows'],static function($r)use($self){return $r['uuid']===$self['uuid'];}));$check(count($matching)===1,'Owned lists positive');foreach($matching[0]as $k=>$v)$check($v===$row[$k],'Every projected source field');$out['cases'][count($out['cases'])-1]['every_projected_source_field_equal']=true;
 $rq($module,'delete','delete',['uuid'=>$self['uuid']],0);++$out['business_dml'];$check($q('SELECT ID FROM '.$p.$self['table'].' WHERE UUID=?',[$self['uuid']])===[],'Actual delete source zero');$rq($module,'delete_repeat','delete',['uuid'=>$self['uuid']],1);$rq($module,'missing_info','info',['uuid'=>'00000000-0000-0000-0000-000000000811'],$module==='gradeEstimation'?1:0);$body=$rq($module,'lists_deleted','lists',['staff_uuid'=>$lease['staff']['uuid']],0);$check(!array_filter($body['data']['rows'],static function($r)use($self){return $r['uuid']===$self['uuid'];}),'Deleted absent from list');
}}catch(Throwable $e){$out['failure']=['class'=>get_class($e),'reason'=>$e->getMessage()];}
finally{foreach($baseline['tables']as $table=>$source)if($source['safe']){$rows=$q('SELECT * FROM '.$p.$table.' ORDER BY ID');$out['natural_tables_returned_to_original'][$table]=$hash($rows)===$source['sha256'];$out['rows_remaining'][$table]=count($rows);}$out['staff_user_reference_unchanged']=$hash($q('SELECT UUID,NAME,AI_USER_ID,IS_SHOW,JOB_STATUS FROM '.$p.'staff WHERE UUID=?',[$lease['staff']['uuid']])[0])===$baseline['synthetic_reference']['staff_projection_sha256']&&$hash($q('SELECT ID,UUID,STAFF_UUID,ACCOUNT,TYPE FROM '.$p.'user WHERE ID=?',[(int)$lease['user']['id']])[0])===$baseline['synthetic_reference']['user_projection_sha256'];foreach(['private-finish.json'=>$out,'private-finish-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);
