<?php
declare(strict_types=1);
require __DIR__.'/bootstrap.php';$before=$snapshot();foreach(['delivery','delivery_rule','goods'] as $t)$check((int)$query('SELECT COUNT(*) n FROM yoshop_'.$t.' WHERE store_id=?',[$tenant])[0]['n']===0,'Fresh tenant collision '.$t);
define('TP_ENV','poc');define('BUSINESS','aizhct');define('ENTERPRISE_NO','10001');require $root.'/vendor/autoload.php';$app=new \think\App($root);$app->setEnvName('poc');$app->setRuntimePath($runtime.'/fixture-runtime/');$app->initialize();$cache=new \think\cache\driver\File($app,['path'=>$runtime.'/cache/','prefix'=>'','expire'=>0]);$token=bin2hex(random_bytes(24));$cache->set($token,['user'=>['store_user_id'=>$tenant,'store_id'=>$tenant,'real_name'=>$marker,'user_name'=>$marker,'is_super'=>1],'store_id'=>$tenant,'is_login'=>true],1800);
$map=['rows'=>['yoshop_delivery'=>[]]];$saveMap=static function()use($runtime,&$map){file_put_contents($runtime.'/private-owned-map.json',json_encode($map));chmod($runtime.'/private-owned-map.json',0600);};$saveMap();$cases=[];$responses=[];$proofs=[];$expected=[];$ids=[];$idMaps=['delivery'=>[],'rule'=>[]];$error=null;$ruleReplacement=[];$deleteProof=[];
$shape=static function($v)use(&$shape){if(is_object($v)){$o=[];foreach(get_object_vars($v) as $k=>$x)$o[$k]=$shape($x);ksort($o);return ['object'=>$o];}if(is_array($v))return ['array'=>array_map($shape,$v)];return gettype($v);};
$request=static function(string $name,string $action,array $data=[])use($base,$token,$check,$shape,&$cases,&$responses):array{$method=in_array($action,['list','all','detail'],true)?'GET':'POST';$scenario='PILOT_DL_'.$name;$path='/terminal/setting.Delivery/'.$action;$h="Host: terminal.delivery-owned.invalid\r\nAccess-Token: ".$token."\r\nPlatform: POC\r\nX-Pilot-Scenario: ".$scenario."\r\nContent-Type: application/json\r\n";$start=time();$raw=file_get_contents($base.$path.($method==='GET'&&$data?'?'.http_build_query($data):''),false,stream_context_create(['http'=>['method'=>$method,'header'=>$h,'content'=>$method==='POST'?json_encode($data,JSON_UNESCAPED_UNICODE):'','timeout'=>30,'ignore_errors'=>true]]));$end=time();$body=json_decode((string)$raw,true);preg_match('#^HTTP/\S+\s+(\d+)#',$http_response_header[0]??'',$m);$check(is_array($body)&&strlen($raw)<1048576,'Actual HTTP JSON');$case=['scenario'=>$scenario,'method'=>$method,'path'=>$path,'http_status'=>(int)($m[1]??0),'body'=>$body,'raw_json_shape'=>$shape(json_decode($raw))];$cases[]=$case;$responses[$scenario]=['raw'=>$raw,'start'=>$start,'end'=>$end];return $case;};
$success=static function(array $c)use($check):void{$check($c['http_status']===200&&($c['body']['status']??0)===200,'Business success '.$c['scenario']);};
$round=static function($v):string{return bcadd(bcadd((string)$v,'0.005',12),'0',2);};
$verify=static function(string $phase)use($query,$check,$tenant,$marker,$round,$saveMap,&$expected,&$ids,&$owned,&$map,&$idMaps,&$proofs):array{$parents=$query('SELECT * FROM yoshop_delivery WHERE store_id=? ORDER BY delivery_id',[$tenant]);$children=$query('SELECT * FROM yoshop_delivery_rule WHERE store_id=? ORDER BY rule_id',[$tenant]);$check(count($parents)===count($expected),'Actual parent cardinality');$by=[];$out=[];$allChildIds=[];
    foreach($parents as $p){$label=null;foreach($expected as $key=>$v)if($p['name']===$v['name'])$label=$key;$check($label!==null&&strpos($p['name'],$marker)===0,'Exact parent marker/name');$e=$expected[$label];$id=(int)$p['delivery_id'];$check($id>0,'Positive parent PK');if(isset($ids[$label]))$check($ids[$label]===$id,'Parent PK stable');$ids[$label]=$id;if(!in_array($id,$owned['delivery'],true))$owned['delivery'][]=$id;if(!isset($idMaps['delivery'][(string)$id]))$idMaps['delivery'][(string)$id]=count($idMaps['delivery'])+1;$map['rows']['yoshop_delivery'][(string)$id]=$tenant;foreach(['method','sort','is_delete'] as $k)$check((int)$p[$k]===(int)$e[$k],'Original parent '.$k);$ruleRows=[];
        foreach($children as $r)if((int)$r['delivery_id']===$id)$ruleRows[]=$r;$check(count($ruleRows)===count($e['rules']),'Actual child cardinality');foreach($ruleRows as $i=>$r){$input=$e['rules'][$i];$check((int)$r['store_id']===$tenant&&(int)$r['delivery_id']===$id,'Child FK independently verified to owned committed parent');foreach(['region','region_text'] as $k)$check(is_string($r[$k])&&json_decode($r[$k],true)===$input[$k],'Original actual JSON/CLOB content '.$k);foreach(['first','additional'] as $k)$check((float)$r[$k]===(float)$input[$k],'Original DOUBLE quantity '.$k);foreach(['first_fee','additional_fee'] as $k)$check(bcadd((string)$r[$k],'0',2)===$round($input[$k]),'Original DECIMAL round '.$k);$rid=(int)$r['rule_id'];$check($rid>0,'Positive child PK');if(!in_array($rid,$owned['delivery_rule'],true))$owned['delivery_rule'][]=$rid;if(!isset($idMaps['rule'][(string)$rid]))$idMaps['rule'][(string)$rid]=count($idMaps['rule'])+1;$allChildIds[]=$rid;}$by[$label]=['parent'=>$p,'rules'=>$ruleRows];$out[]=['label'=>$label,'parent_pk_stable'=>true,'child_rows'=>count($ruleRows),'all_input_values_and_fk_verified'=>true];}
    $check(count($allChildIds)===count($children),'No orphan owned child rows');$saveMap();$proofs[]=['phase'=>$phase,'parents'=>count($parents),'children'=>count($children),'rows'=>$out,'new_child_fk_verified_independently_after_commit'=>true];return $by;};
$parentProject=static function(array $r)use($check):array{foreach(['delivery_id','method','sort','is_delete','store_id'] as $k)$r[$k]=(int)$r[$k];foreach(['create_time','update_time'] as $k){$check(is_numeric($r[$k])&&(int)$r[$k]>0,'Actual parent Unix time');$r[$k]=date('Y-m-d H:i:s',(int)$r[$k]);}return $r;};
$ruleProject=static function(array $r)use($check):array{foreach(['rule_id','delivery_id','store_id'] as $k)$r[$k]=(int)$r[$k];foreach(['region','region_text'] as $k){$r[$k]=json_decode($r[$k],true);$check(is_array($r[$k]),'Actual child JSON arrays');}foreach(['first','additional'] as $k)$r[$k]=json_decode(json_encode((float)$r[$k]),true);foreach(['first_fee','additional_fee'] as $k)$r[$k]=bcadd((string)$r[$k],'0',2);$check((int)$r['create_time']>0,'Actual child Unix time');$r['create_time']=date('Y-m-d H:i:s',(int)$r['create_time']);return $r;};
$read=static function(string $name,string $action,array $args=[])use($request,$success,$query,$tenant,$parentProject,$ruleProject,$check,&$cases):void{$c=$request($name,$action,$args);$success($c);if($action==='detail'){$p=$query('SELECT * FROM yoshop_delivery WHERE delivery_id=? AND store_id=?',[$args['deliveryId'],$tenant]);$check(count($p)===1,'Detail existing original');$rows=[$p[0]];}else{$sql='SELECT * FROM yoshop_delivery WHERE store_id=? AND is_delete=0';$bind=[$tenant];if(isset($args['search'])){$sql.=' AND name LIKE ?';$bind[]='%'.$args['search'].'%';}$rows=$query($sql.' ORDER BY sort,delivery_id',$bind);}
    $out=[];foreach($rows as $r){$p=$parentProject($r);if($action!=='all')$p['rule']=array_map($ruleProject,$query('SELECT * FROM yoshop_delivery_rule WHERE delivery_id=? AND store_id=? ORDER BY rule_id',[$r['delivery_id'],$tenant]));$out[]=$p;}$want=$action==='detail'?['detail'=>$out[0]]:($action==='all'?['list'=>$out]:['list'=>['total'=>count($out),'per_page'=>15,'current_page'=>1,'last_page'=>count($out)?1:0,'data'=>$out]]);$check($c['body']['data']===$want,'Complete original wire/fields/values/types/order '.$name);$cases[count($cases)-1]['complete_original_projection_equal']=true;};
try{
    $cities=$query('SELECT id,pid,name FROM yoshop_region WHERE '.($dm?'"LEVEL"':'level').'=2 ORDER BY id');$check(count($cities)>=2,'Two actual region cities');$makeRegion=static function(array $city)use($query,$check):array{$province=$query('SELECT id,name FROM yoshop_region WHERE id=?',[$city['pid']]);$check(count($province)===1,'Actual region parent');return ['region'=>[(int)$city['id']],'region_text'=>[['id'=>(int)$province[0]['id'],'name'=>$province[0]['name'],'citys'=>[['id'=>(int)$city['id'],'name'=>$city['name']]]]]];};$r1=$makeRegion($cities[0]);$r2=$makeRegion($cities[1]);
    $rule1=$r1+['first'=>1,'first_fee'=>0,'additional'=>1,'additional_fee'=>0.01];$rule2=$r2+['first'=>2,'first_fee'=>1.25,'additional'=>0,'additional_fee'=>2.50];$formA=['name'=>$marker."_甲'配送\\餐",'method'=>10,'sort'=>100,'rules'=>[$rule1,$rule2]];$c=$request('ADD_A_TWO_RULES','add',['form'=>$formA]);$success($c);$expected['A']=$formA+['is_delete'=>0];$a=$verify('A_CREATED');$read('DETAIL_A_CREATED','detail',['deliveryId'=>$ids['A']]);$read('LIST_A_CREATED','list');$read('ALL_A_CREATED','all');
    $formB=['name'=>$marker.'_乙配送','method'=>10,'sort'=>0,'rules'=>[$rule2]];$c=$request('ADD_B_ONE_RULE','add',['form'=>$formB]);$success($c);$expected['B']=$formB+['is_delete'=>0];$rows=$verify('B_CREATED');$read('LIST_TWO_SORT','list');$read('ALL_TWO_SORT','all');$beforeB=$rows['B'];$oldAIds=array_column($rows['A']['rules'],'rule_id');
    $edit=$formA;$edit['name']=$marker."_改'配送\\餐";$edit['method']=20;$edit['sort']=2;$edit['rules'][0]['first']=0.25;$edit['rules'][0]['additional']=0.5;$edit['rules'][0]['first_fee']=1.005;$edit['rules'][0]['additional_fee']=0.105;$edit['rules'][1]['first']=1.75;$edit['rules'][1]['additional']=0.25;$edit['rules'][1]['first_fee']=2.345;$edit['rules'][1]['additional_fee']=0;$c=$request('EDIT_A_REPLACE_RULES','edit',['deliveryId'=>$ids['A'],'form'=>$edit]);$success($c);$expected['A']=$edit+['is_delete'=>0];$rows=$verify('A_EDITED_REPLACED');$check($rows['B']===$beforeB,'Unmodified B original parent/child rows unchanged');$check(!array_intersect(array_map('intval',$oldAIds),array_map('intval',array_column($rows['A']['rules'],'rule_id'))),'Old/new rule PK disjoint');foreach($oldAIds as $old)$check((int)$query('SELECT COUNT(*) n FROM yoshop_delivery_rule WHERE rule_id=?',[$old])[0]['n']===0,'Old owned rule physically removed');$ruleReplacement=['old_rules_physical_remaining'=>0,'new_rules'=>2,'parent_pk_same'=>true,'other_parent_child_raw_unchanged'=>true];$read('DETAIL_A_EDITED','detail',['deliveryId'=>$ids['A']]);$read('LIST_AFTER_EDIT','list');$read('ALL_AFTER_EDIT','all');$read('SEARCH_QUOTE_NONEMPTY','list', ['search'=>"改'配送"]);$read('SEARCH_EMPTY','list',['search'=>$marker.'_NOTFOUND']);
    $beforeBad=$rows;$bad=$edit;$bad['rules']=[];$c=$request('EMPTY_RULES_REFUSAL','edit',['deliveryId'=>$ids['A'],'form'=>$bad]);$check($c['http_status']===200&&$c['body']['status']===500&&$c['body']['message']==='请选择可配送区域','Original empty-rule validation');$check($verify('EMPTY_RULES_NO_WRITE')===$beforeBad,'Rejected edit original both tables unchanged');
    $check((int)$query('SELECT COUNT(*) n FROM yoshop_goods WHERE delivery_id=? AND store_id=? AND is_delete=0',[$ids['A'],$tenant])[0]['n']===0,'Independent no active goods reference');$beforeDelete=$rows['A']['rules'];$c=$request('DELETE_A_SOFT','delete',['deliveryId'=>$ids['A']]);$success($c);$expected['A']['is_delete']=1;$rows=$verify('A_SOFT_DELETED');$check($rows['A']['rules']===$beforeDelete,'Parent soft-delete retains child original rows');$fresh=$connect();$s=$fresh->prepare('SELECT is_delete FROM yoshop_delivery WHERE delivery_id=? AND store_id=?');$s->execute([$ids['A'],$tenant]);$check((int)$s->fetchColumn()===1,'New PDO actual parent soft flag');$deleteProof=['parent_is_delete'=>1,'parent_physical_remaining'=>1,'child_rows_retained'=>2,'child_raw_unchanged'=>true,'no_active_goods_reference'=>true];$read('LIST_AFTER_SOFT_DELETE','list');$read('ALL_AFTER_SOFT_DELETE','all');$read('DETAIL_SOFT_DELETED_ORIGINAL_BEHAVIOR','detail',['deliveryId'=>$ids['A']]);
}catch(Throwable $caught){$error=['class'=>get_class($caught),'message'=>$caught->getMessage(),'file'=>basename($caught->getFile()),'line'=>$caught->getLine()];}
$cache->delete($token);$tokenGone=$cache->get($token)===null;$cache->clear();$cacheFiles=0;if(is_dir($runtime.'/cache/'))foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($runtime.'/cache/',FilesystemIterator::SKIP_DOTS)) as $f)if($f->isFile())$cacheFiles++;
$after=$snapshot();$private=['lane'=>$lane,'marker'=>$marker,'tenant'=>$tenant,'owned_primary_keys'=>$owned,'ids'=>$ids,'id_maps'=>$idMaps,'expected'=>$expected,'cases'=>$cases,'responses'=>$responses,'before'=>$before,'after'=>$after];file_put_contents($runtime.'/private-retention.json',json_encode($private,JSON_PRETTY_PRINT|JSON_PRESERVE_ZERO_FRACTION|JSON_UNESCAPED_UNICODE));chmod($runtime.'/private-retention.json',0600);
$normal=static function($x)use(&$normal,$idMaps){if(!is_array($x))return $x;foreach($x as $k=>&$v){if($k==='delivery_id'&&is_int($v)&&isset($idMaps['delivery'][(string)$v]))$v=$idMaps['delivery'][(string)$v];elseif($k==='rule_id'&&is_int($v)&&isset($idMaps['rule'][(string)$v]))$v=$idMaps['rule'][(string)$v];elseif(in_array($k,['create_time','update_time'],true)&&is_string($v)&&preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/D',$v))$v='VERIFIED_OWN_ORIGINAL_TIME';else $v=$normal($v);}unset($v);return $x;};
foreach($cases as &$c){$trace=$c['body']['trace_id']??null;$c['trace_format_valid']=is_string($trace)&&preg_match('/^[0-9a-f]{13}$/D',$trace)===1;if($c['trace_format_valid'])$c['body']['trace_id']='VALID_DYNAMIC_TRACE';if($c['body']['status']===500&&$c['scenario']!=='PILOT_DL_EMPTY_RULES_REFUSAL'){$c['private_unexpected_error_message_sha256']=hash('sha256',$c['body']['message']);$c['body']['message']='UNEXPECTED_ERROR_FULL_WIRE_PRIVATE';}}unset($c);$events=[];foreach(file($runtime.'/queries.jsonl',FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES)?:[] as $l)$events[]=json_decode($l,true);$audit=[];foreach(file($runtime.'/write-audit.jsonl',FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES)?:[] as $l)$audit[]=json_decode($l,true);
$fresh=$connect();$retained=[];foreach(['delivery','delivery_rule'] as $t){$s=$fresh->prepare('SELECT COUNT(*) FROM yoshop_'.$t.' WHERE store_id=?');$s->execute([$tenant]);$retained[$t]=(int)$s->fetchColumn();}
$report=['lane'=>$lane,'cases'=>$normal($cases),'original_proofs'=>$proofs,'rule_replacement'=>$ruleReplacement,'soft_delete'=>$deleteProof,'retention'=>['mode'=>'retained-owned','fresh_counts'=>$retained,'natural_two_table_sha_unchanged'=>$before===$after,'exact_owned_pks_only'=>true,'large_table_full_sha_claimed'=>false],'resources'=>['token_absent'=>$tokenGone,'cache_files'=>$cacheFiles],'error'=>$error,'events'=>$events,'write_audit'=>$audit,'loaded_boundary'=>$boundary];file_put_contents($runtime.'/report.json',json_encode($report,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE));echo json_encode(['lane'=>$lane,'http_cases'=>count($cases),'retained'=>$retained,'natural_sha_unchanged'=>$before===$after,'error'=>$error,'report'=>$runtime.'/report.json']),"\n";exit($error!==null||$before!==$after||!$tokenGone||$cacheFiles||in_array(false,array_column($audit,'owned_scope_verified'),true)?1:0);
