<?php
declare(strict_types=1);$lane=getenv('CORE_LANE');$dm=getenv('POC_DIALECT')==='dm';$file=__DIR__.'/private/prepare-validation-'.$lane.'.json';if(is_file($file))throw new RuntimeException('Exact validation once');$pre=json_decode(file_get_contents(__DIR__.'/private/preflight-'.$lane.'.json'),true);$plan=json_decode(file_get_contents(__DIR__.'/typed-prepare-plan.json'),true);$errors=[];$seen=[];$types=[];foreach($plan['rows'] as $entry){$db=$entry['connection']==='mysql'?'AI':'ZHCT';$table=substr($entry['table'],strlen($db==='AI'?'yoshop_':'ydy_'));$columns=[];foreach($pre['schema'][$db][$table]['columns'] as $column)$columns[strtolower($column['column_name'])]=$column;foreach($entry['values'] as $key=>[$type,$value]){if(!isset($columns[$key])){$errors[]=$entry['name'].'.'.$key.' missing column';continue;}$c=$columns[$key];$length=$c['character_maximum_length']??null;if($length!==null&&$type==='str'&&strlen($value)>$length)$errors[]=$entry['name'].'.'.$key.' too long';if($type==='ref'&&!isset($seen[$value]))$errors[]=$entry['name'].'.'.$key.' unresolved prior real identity';$types[$entry['name']][$key]=$c['data_type'];}foreach($columns as $name=>$c){$nn=($c['is_nullable']??'')==='NO'||($c['nullable']??'')==='N';$default=$c['column_default']??$c['data_default']??null;if($name!==$entry['pk']&&$nn&&$default===null&&!array_key_exists($name,$entry['values']))$errors[]=$entry['name'].'.'.$name.' NN/no-default missing';}$seen[$entry['name']]=true;}
$pdo=[];foreach(['AI','ZHCT'] as $db){$dsn=$dm?'dm:host=127.0.0.1;port='.getenv('POC_'.$db.'_PORT').';schema='.getenv('POC_'.$db.'_SCHEMA'):'mysql:host='.getenv('POC_'.$db.'_HOST').';port='.getenv('POC_'.$db.'_PORT').';dbname='.getenv('POC_'.$db.'_SCHEMA').';charset='.getenv('POC_'.$db.'_CHARSET');$pdo[$db]=new PDO($dsn,getenv('POC_'.$db.'_USER'),getenv('POC_'.$db.'_PASSWORD'),[PDO::ATTR_CASE=>PDO::CASE_LOWER,PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_EMULATE_PREPARES=>false]);}
$queries=[['AI','SELECT COUNT(*) n FROM yoshop_user WHERE nick_name IN (?,?) OR mobile IN (?,?)',['CDXCORE11S1_U1','CDXCORE11S1_U2','00000001111','00000001112']],['ZHCT','SELECT COUNT(*) n FROM ydy_user WHERE uuid IN (?,?) OR account IN (?,?) OR mobile IN (?,?)',['f4c61111-2026-4a11-8111-000000000001','f4c61111-2026-4a11-8111-000000000002','CDXCORE11S1_U1','CDXCORE11S1_U2','00000001111','00000001112']],['ZHCT','SELECT COUNT(*) n FROM ydy_staff WHERE uuid=? OR personnel_umber=? OR mobile=?',['f4c61111-2026-4a11-8111-000000000101','CDXCORE11S1_U1','00000001111']],['ZHCT','SELECT COUNT(*) n FROM ydy_restaurants WHERE uuid=? OR name=?',['f4c61111-2026-4a11-8111-000000000201','CDXCORE11S1_R1']],['ZHCT','SELECT COUNT(*) n FROM ydy_prepay_order WHERE device_order_no=? OR machid=? OR goods_name=?',['CDXCORE11S1_PP1','CDXCORE11S1_M1','CDXCORE11S1_COFFEE']],['ZHCT','SELECT COUNT(*) n FROM ydy_staff_department WHERE staff_uuid=?',['f4c61111-2026-4a11-8111-000000000101']],['ZHCT','SELECT COUNT(*) n FROM ydy_one_card_account_map WHERE staff_uuid=? AND acc_num<>?',['f4c61111-2026-4a11-8111-000000000101','']]];$events=[];foreach($queries as [$db,$sql,$params]){$s=$pdo[$db]->prepare($sql);$bind=[];foreach($params as $i=>$v){$s->bindValue($i+1,$v,PDO::PARAM_STR);$bind[]=['position'=>$i+1,'value'=>$v,'pdo_type'=>PDO::PARAM_STR];}$s->execute();$rows=$s->fetchAll(PDO::FETCH_ASSOC);if((int)$rows[0]['n']!==0)$errors[]='Collision for '.$sql;$events[]=['connection'=>$db,'operation'=>'SELECT','queryString'=>$s->queryString,'bindValue'=>$bind,'execute_success'=>true,'rows'=>$rows];}
$result=['lane'=>$lane,'HTTP'=>0,'DML'=>0,'DDL'=>0,'SELECT'=>count($events),'proposed_rows'=>7,'plan_sha256'=>hash_file('sha256',__DIR__.'/typed-prepare-plan.json'),'errors'=>$errors,'field_physical_types'=>$types,'native_events'=>$events,'new_actor_post_prepare_Guard_still_required'=>true];file_put_contents($file,json_encode($result,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES|JSON_PRESERVE_ZERO_FRACTION));chmod($file,0600);echo json_encode(['lane'=>$lane,'HTTP'=>0,'DML'=>0,'DDL'=>0,'SELECT'=>count($events),'rows_schema_validated'=>7,'errors'=>$errors]),"\n";
