<?php
declare(strict_types=1);
date_default_timezone_set('Asia/Shanghai');require __DIR__.'/common.php';
set_exception_handler(static function(Throwable $e):void{smSave('run-error-private.json',['class'=>get_class($e),'file'=>$e->getFile(),'line'=>$e->getLine(),'message'=>$e->getMessage()]);echo json_encode(['status'=>'tool_or_precondition_failure','class'=>get_class($e),'file'=>basename($e->getFile()),'line'=>$e->getLine(),'message_sha256'=>hash('sha256',$e->getMessage())]),PHP_EOL;exit(1);});
$lane=getenv('SM7_LANE');$runtime=getenv('SM7_RUNTIME');$root=getenv('SM7_ROOT');$base=getenv('SM7_BASE');$pre=smLoad('preflight-private.json');$actor=smLoad('actor-private.json');$db=smPdo();
if(!in_array($base,['http://127.0.0.1:18391','http://127.0.0.1:18392'],true)){throw new RuntimeException('Private target');}
$own=smRows($db,'SELECT id,uuid,account,create_by,type,status FROM ydy_user WHERE id=? AND uuid=? AND account=? AND create_by=?',[$actor['id'],$actor['uuid'],$actor['marker'],$actor['marker']]);if(count($own)!==1||(int)$own[0]['type']!==0||(int)$own[0]['status']!==0){throw new RuntimeException('Owned disabled actor drift');}
require_once $root.'/application/base/Security.php';$token=\app\base\Security::encrypt(implode("\t",[(string)$actor['id'],$actor['uuid'],$actor['marker'],'0','','',$actor['marker']]));
$boundary=json_decode(file_get_contents($base.'/__poc_boundary'),true);if(!is_array($boundary)||empty($boundary['private_source_reflection'])||empty($boundary['file_cache'])||empty($boundary['redis_disabled'])||empty($boundary['external_stubs'])||$boundary['real_queue']!==false){throw new RuntimeException('Actual HTTP boundary rejected');}
$r=$pre['recipe'];if(!$r){throw new RuntimeException('No recipe source; do not fake positive');}$hw=$pre['hardware']??['staff_uuid'=>$r['staff_uuid'],'menu_date'=>$r['date'],'meal_times'=>$r['meal']];$check=$pre['check']??['staff_uuid'=>$r['staff_uuid'],'menu_date'=>$r['date'],'meal_times'=>$r['meal'],'department_uuid'=>'CDXDMENU10_NO_DEPARTMENT'];
$defs=[
 ['DISHES','/p/dateMenu/getDishes',['staff_uuid'=>$r['staff_uuid'],'recipe_uuids'=>'','date'=>$r['date'],'type'=>$r['category'],'meal_times'=>$r['meal'],'type_plus'=>2]],
 ['RECIPE_INFO','/p/dateMenu/getRecipeInfo',['date'=>$r['date'],'meal'=>$r['meal']]],
 ['HARDWARE','/p/date_menu/hardwareInfo',['staff_uuid'=>$hw['staff_uuid'],'menu_date'=>substr((string)$hw['menu_date'],0,10),'meal_times'=>$hw['meal_times'],'type'=>1]],
 ['CHECK_MENU','/p/dateMenu/checkMenuList',['department_uuid'=>$check['department_uuid'],'date'=>substr((string)$check['menu_date'],0,10),'staff_name'=>'','page'=>1,'page_size'=>5,'meal_times'=>$check['meal_times']]],
 ['VERSION_LIST','/p/equipment/VersionList',['page'=>1,'pageSize'=>5,'type'=>'']],
 ['VERSION_READ','/p/equipment/versionRead',['uuid'=>$pre['versions'][0]['uuid']??'CDXDMENU10_NO_VERSION']],
 ['CONSUME_LIST','/p/equipment/consumeList',[]],
 ['VERSION_MISSING','/p/equipment/versionRead',['uuid'=>'CDXDMENU10_NO_SUCH_VERSION']],
 ['VERSION_PAGE2','/p/equipment/VersionList',['page'=>2,'pageSize'=>5,'type'=>'']],
];
$queries=[
 ['SELECT * FROM ydy_equipment_version',[]],
 ['SELECT * FROM ydy_equipment',[]],
 ["SELECT config_key,config_value,status FROM ydy_config WHERE config_key IN ('ossDisjunctor','ossHost','businessIdentify','morning_start','morning_end','noon_start','noon_end','night_start','night_end')",[]],
 ['SELECT * FROM ydy_recipes WHERE menu_date=? AND meal_times=?',[$r['date'],$r['meal']]],
 ['SELECT * FROM ydy_dishes WHERE category=? AND status=1 AND is_del=1',[$r['category']]],
 ['SELECT * FROM ydy_initial_menu WHERE staff_uuid=? AND menu_date=? AND meal_times=?',[$hw['staff_uuid'],substr((string)$hw['menu_date'],0,10),$hw['meal_times']]],
 ['SELECT * FROM ydy_initial_menu_log WHERE staff_uuid=? AND menu_date=? AND meal_times=?',[$hw['staff_uuid'],substr((string)$hw['menu_date'],0,10),$hw['meal_times']]],
 ['SELECT * FROM ydy_date_menu_hardware_img WHERE staff_uuid=? AND menu_date=? AND meal_times=?',[$hw['staff_uuid'],substr((string)$hw['menu_date'],0,10),$hw['meal_times']]],
 ['SELECT * FROM ydy_initial_menu WHERE menu_date=? AND meal_times=? AND meal_type IN (1,4)',[substr((string)$check['menu_date'],0,10),$check['meal_times']]],
 ['SELECT * FROM ydy_staff_department WHERE department_uuid=?',[$check['department_uuid']]],
 ['SELECT * FROM ydy_department WHERE uuid=? OR department_path LIKE ?',[$check['department_uuid'],'%'.$check['department_uuid'].'%']],
 ['SELECT * FROM ydy_staff WHERE uuid=? OR uuid=?',[$r['staff_uuid'],$hw['staff_uuid']]],
];
$snapshot=static function()use($db,$queries):array{$out=[];foreach($queries as $i=>[$sql,$args]){$out[$i]=smDigest(smRows($db,$sql,$args));}return $out;};$before=$snapshot();$bodies=[];$cases=[];$error=null;
try{foreach($defs as [$name,$path,$params]){$options=['method'=>'POST','header'=>"Host: cdx-store-menu7.invalid\r\nContent-Type: application/x-www-form-urlencoded;charset=UTF-8\r\ntoken: ".$token."\r\nX-Pilot-Scenario: PILOT_SM7_".$name."\r\n",'content'=>http_build_query($params),'ignore_errors'=>true,'follow_location'=>0,'timeout'=>35];$raw=file_get_contents($base.$path,false,stream_context_create(['http'=>$options]));preg_match('~^HTTP/\S+ (\d+)~',$http_response_header[0]??'',$m);$status=(int)($m[1]??0);$body=json_decode((string)$raw);$bodies[$name]=['method'=>'POST','path'=>$path,'params'=>$params,'http_status'=>$status,'body'=>$body,'wire_bytes'=>strlen((string)$raw),'wire_sha256'=>hash('sha256',(string)$raw)];$cases[]=['case'=>$name,'method'=>'POST','path'=>$path,'http_status'=>$status,'code'=>$body->code??null,'data_count'=>isset($body->data)&&is_array($body->data)?count($body->data):null,'message_type'=>isset($body->message)?gettype($body->message):null];}}
catch(Throwable $e){$error=['class'=>get_class($e),'message_sha256'=>hash('sha256',$e->getMessage())];}
$after=$snapshot();$events=[];foreach(file($runtime.'/queries.jsonl',FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES)?:[] as $line){$events[]=json_decode($line,true);}$writes=0;foreach($events as $e){if($e['kind']==='query_observed'&&in_array($e['operation'],['insert','update','delete','merge','replace'],true)){$writes++;}}
$actualSha=[];foreach($pre['source_sha256'] as $file=>$oldSha){$actualSha[$file]=hash_file('sha256',$root.'/'.$file);if($actualSha[$file]!==$oldSha&&!($file==='application/p/logic/DateMenu.php'&&$actualSha[$file]==='4749b69e8e4de3cfd0c05eb4be1a9cf182a7a22182d7c020a9cd48c60f7e44e3')){throw new RuntimeException('Unexpected runtime source drift');}}
$naturalUser=smUserDigest($db,$actor['id']);$report=['lane'=>$lane,'cases'=>$cases,'boundary'=>$boundary,'unexpected'=>$error,'source_before'=>$before,'source_after'=>$after,'source_unchanged'=>$before===$after,'natural_user_unchanged'=>$naturalUser===$pre['natural_user_before'],'retained_actor'=>['id'=>$actor['id'],'uuid'=>$actor['uuid'],'marker'=>$actor['marker'],'type'=>0,'status'=>0],'http_dml'=>$writes,'events'=>$events,'source_sha256'=>$actualSha,'source_queries_private'=>$queries,'hardware_nonempty_source'=>$pre['hardware']!==null,'check_nonempty_source'=>$pre['check']!==null];
smSave('responses-private.json',$bodies);smSave('report-private.json',$report);echo json_encode(['lane'=>$lane,'cases'=>$cases,'unexpected'=>$error!==null,'source_unchanged'=>$report['source_unchanged'],'natural_user_unchanged'=>$report['natural_user_unchanged'],'http_dml'=>$writes]),PHP_EOL;exit($error!==null||!$report['source_unchanged']||!$report['natural_user_unchanged']||$writes?1:0);
