<?php
declare(strict_types=1);
$lane=getenv('ROPE_LANE');$dm=getenv('POC_DIALECT')==='dm';$private=__DIR__.'/private';if(!is_dir($private))mkdir($private,0700);chmod($private,0700);
$options=[PDO::ATTR_CASE=>PDO::CASE_LOWER,PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_ORACLE_NULLS=>PDO::NULL_NATURAL,PDO::ATTR_STRINGIFY_FETCHES=>false,PDO::ATTR_EMULATE_PREPARES=>false];
$dsn=$dm?'dm:host=127.0.0.1;port=5238;schema=AIZHCT_APP':'mysql:host='.getenv('POC_AI_HOST').';port='.getenv('POC_AI_PORT').';dbname='.getenv('POC_AI_SCHEMA').';charset='.getenv('POC_AI_CHARSET');
$pdo=new PDO($dsn,getenv('POC_AI_USER'),getenv('POC_AI_PASSWORD'),$options);$records=[];
$q=static function($sql,$params=[])use($pdo,&$records,$private,$lane){
 if(!preg_match('/^SELECT\b/',$sql)||preg_match('/;|\b(?:INSERT|UPDATE|DELETE|ALTER|CREATE|DROP|INTO|CALL)\b/i',$sql))throw new RuntimeException('Preflight SELECT gate');
 $bind=[];try{$s=$pdo->prepare($sql);foreach(array_values($params) as $i=>$v){$s->bindValue($i+1,(string)$v,PDO::PARAM_STR);$bind[]=['position'=>$i+1,'value'=>(string)$v,'pdo_type'=>PDO::PARAM_STR];}$s->execute();$rows=$s->fetchAll(PDO::FETCH_ASSOC);foreach($rows as &$row)foreach($row as &$v)if(is_resource($v))$v=stream_get_contents($v);unset($row,$v);$record=['queryString'=>$s->queryString,'bindValue'=>$bind,'rowCount'=>$s->rowCount(),'rows'=>$rows];}catch(Throwable $e){$record=['queryString'=>$sql,'bindValue'=>$bind,'planned_values'=>$params,'error'=>['class'=>get_class($e),'code'=>$e->getCode(),'message'=>$e->getMessage()]];file_put_contents($private.'/preflight-attempts-'.$lane.'.jsonl',json_encode($record,JSON_UNESCAPED_UNICODE|JSON_PRESERVE_ZERO_FRACTION)."\n",FILE_APPEND|LOCK_EX);chmod($private.'/preflight-attempts-'.$lane.'.jsonl',0600);throw $e;}$records[]=$record;file_put_contents($private.'/preflight-attempts-'.$lane.'.jsonl',json_encode($record,JSON_UNESCAPED_UNICODE|JSON_PRESERVE_ZERO_FRACTION)."\n",FILE_APPEND|LOCK_EX);chmod($private.'/preflight-attempts-'.$lane.'.jsonl',0600);return $rows;
};
$identity=$q($dm?"SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') schema_name FROM DUAL":'SELECT DATABASE() schema_name, VERSION() version, @@SESSION.sql_mode sql_mode, @@character_set_connection connection_charset');
if($identity[0]['schema_name']!==($dm?'AIZHCT_APP':getenv('POC_AI_SCHEMA'))||(!$dm&&strpos($identity[0]['version'],'5.6.')!==0))throw new RuntimeException('Approved database drift');
$schema=[];$tables=['rope_skipping','user','staff','store','store_setting','user_oauth'];
foreach($tables as $name){$t='yoshop_'.$name;$u=strtoupper($t);
 $cols=$q($dm?'SELECT COLUMN_NAME,DATA_TYPE,NULLABLE,DATA_DEFAULT,DATA_LENGTH,DATA_PRECISION,DATA_SCALE FROM USER_TAB_COLUMNS WHERE TABLE_NAME=? ORDER BY COLUMN_ID':'SELECT COLUMN_NAME,DATA_TYPE,COLUMN_TYPE,IS_NULLABLE,COLUMN_DEFAULT,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE,EXTRA FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=? ORDER BY ORDINAL_POSITION',[$dm?$u:$t]);
 $fk=$q($dm?"SELECT CONSTRAINT_NAME,CONSTRAINT_TYPE,TABLE_NAME,R_CONSTRAINT_NAME FROM USER_CONSTRAINTS WHERE CONSTRAINT_TYPE='R' AND (TABLE_NAME=? OR R_CONSTRAINT_NAME IN (SELECT CONSTRAINT_NAME FROM USER_CONSTRAINTS WHERE TABLE_NAME=?))":'SELECT TABLE_NAME,CONSTRAINT_NAME,COLUMN_NAME,REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA=DATABASE() AND REFERENCED_TABLE_NAME IS NOT NULL AND (TABLE_NAME=? OR REFERENCED_TABLE_NAME=?)',[$dm?$u:$t,$dm?$u:$t]);
 $tr=$q($dm?'SELECT * FROM USER_TRIGGERS WHERE TABLE_NAME=?':'SELECT TRIGGER_NAME,EVENT_MANIPULATION,ACTION_TIMING,ACTION_STATEMENT FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_SCHEMA=DATABASE() AND EVENT_OBJECT_TABLE=?',[$dm?$u:$t]);
 $indexes=$q($dm?'SELECT INDEX_NAME,UNIQUENESS FROM USER_INDEXES WHERE TABLE_NAME=? ORDER BY INDEX_NAME':'SELECT INDEX_NAME,NON_UNIQUE,COLUMN_NAME,SEQ_IN_INDEX FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=? ORDER BY INDEX_NAME,SEQ_IN_INDEX',[$dm?$u:$t]);
 $schema[$name]=['columns'=>$cols,'foreign_keys'=>$fk,'triggers'=>$tr,'indexes'=>$indexes];
 if($dm)$schema[$name]['ddl']=$q("SELECT DBMS_METADATA.GET_DDL('TABLE',?,'AIZHCT_APP') ddl FROM DUAL",[$u]);
}
$users=$lane==='B'?[46914,46915]:[1928,1929];$staff=$lane==='B'?[46334,46335]:[1851,1852];
$userCols=array_column($schema['user']['columns'],'column_name');$userCols=array_map('strtolower',$userCols);$select=['user_id','store_id','nick_name','is_delete'];foreach(['password_version','password_status'] as $c)if(in_array($c,$userCols,true))$select[]=$c;
$ownUsers=$q('SELECT '.implode(',',$select).' FROM yoshop_user WHERE user_id IN (?,?) AND store_id IN (?,?) ORDER BY user_id',array_merge($users,[2147001111,2147001112]));
$ownStaff=$q('SELECT id,user_id,store_id,name,create_by,is_delete FROM yoshop_staff WHERE id IN (?,?) AND store_id IN (?,?) ORDER BY id',array_merge($staff,[2147001111,2147001112]));
if(count($ownUsers)!==2||count($ownStaff)!==2)throw new RuntimeException('Missing retained own actors');
foreach($ownUsers as $i=>$u){if((int)$u['user_id']!==$users[$i]||(int)$u['is_delete']!==0||strpos($u['nick_name'],'CDX')!==0||(int)$ownStaff[$i]['user_id']!==$users[$i]||(int)$ownStaff[$i]['store_id']!==(int)$u['store_id']||(int)$ownStaff[$i]['is_delete']!==0||$ownStaff[$i]['create_by']!=='CDXRR11A8F4')throw new RuntimeException('Retained marked ownership mismatch');}
$stores=$q('SELECT store_id,is_delete,is_recycle FROM yoshop_store WHERE store_id IN (?,?) ORDER BY store_id',[2147001111,2147001112]);
$existing=$q('SELECT id,user_id,store_id,mac,date_key,CAST(stopped_at AS '.($dm?'VARCHAR(40)':'CHAR').') stopped_at_exact,is_delete FROM yoshop_rope_skipping WHERE store_id IN (?,?) AND user_id IN (?,?) ORDER BY id',array_merge([2147001111,2147001112],$users));
$collision=$q('SELECT id FROM yoshop_rope_skipping WHERE mac LIKE ?',['CDXRE11D7C2_%']);
$oauth=$q('SELECT user_id,store_id,oauth_type,is_delete FROM yoshop_user_oauth WHERE user_id IN (?,?) AND store_id IN (?,?) ORDER BY user_id',array_merge($users,[2147001111,2147001112]));
require getenv('ROPE_SOURCE').'/vendor/autoload.php';require (getenv('ROPE_VALIDATOR')?:getenv('ROPE_SOURCE').'/app/api/validate/RopeSkippingValidate.php');$validator=[];
foreach(['1790000000123','9007199254740991','9007199254740993','9223372036854775807','0','-1','9223372036854775808','18446744073709551615','1.5','abc',null,[],true] as $value){$v=new \app\api\validate\RopeSkippingValidate();$v->setLang(new \think\Lang(new \think\App(getenv('ROPE_SOURCE'))));$ok=$v->scene('add')->check(['mac'=>'CDXRE11D7C2_DRY','mode'=>'free','dateKey'=>'2097-11-01','stoppedAt'=>$value]);$validator[]=['input'=>$value,'php_type'=>gettype($value),'accepted'=>$ok,'error'=>$ok?null:$v->getError(),'service_int'=>$ok?(string)(int)$value:null];}
$port=$lane==='B'?18901:18902;$socket=@fsockopen('127.0.0.1',$port,$e,$m,1);$portCollision=$socket!==false;if($socket)fclose($socket);
$raw=['lane'=>$lane,'identity'=>$identity,'pdo_options'=>$options,'schema'=>$schema,'users'=>$ownUsers,'staff'=>$ownStaff,'stores'=>$stores,'existing_own_rope'=>$existing,'marker_collision'=>$collision,'own_oauth'=>$oauth,'validator'=>$validator,'port'=>$port,'port_collision'=>$portCollision,'HTTP'=>0,'DML'=>0,'DDL'=>0,'queries'=>$records];
$json=json_encode($raw,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES|JSON_PRESERVE_ZERO_FRACTION);if($json===false)throw new RuntimeException('Evidence encoding failure');$file=$private.'/preflight-'.$lane.'.json';if(file_exists($file))throw new RuntimeException('Existing evidence must not overwrite');file_put_contents($file,$json);chmod($file,0600);
$out=['lane'=>$lane,'HTTP'=>0,'DML'=>0,'DDL'=>0,'SELECT'=>count($records),'schema_column_counts'=>array_map(static function($s){return count($s['columns']);},$schema),'fk_counts'=>array_map(static function($s){return count($s['foreign_keys']);},$schema),'trigger_counts'=>array_map(static function($s){return count($s['triggers']);},$schema),'marked_users'=>count($ownUsers),'marked_staff'=>count($ownStaff),'existing_own_rope'=>count($existing),'marker_collision'=>count($collision),'port_collision'=>$portCollision,'validator'=>$validator,'raw_bytes'=>strlen($json),'raw_sha256'=>hash('sha256',$json)];file_put_contents(__DIR__.'/preflight-'.$lane.'.json',json_encode($out,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE));echo json_encode($out,JSON_UNESCAPED_UNICODE),"\n";
