<?php
require __DIR__.'/common.php';
if(is_file(__DIR__.'/private/fixture-attempt.json'))throw new RuntimeException('Fixture attempts never replay');
$pre=json_decode(file_get_contents(__DIR__.'/private/preflight-'.$lane.'.json'),true);
$before=$source();foreach(['nutrition','nutrition_template','nutrition_template_ext','nutrition_set','nutrition_category','nutrition_time']as $t)if($before[$t]!==[])throw new RuntimeException('Own marker collision');
if($before['actor']!==$pre['actor'])throw new RuntimeException('Exact actor drift');
foreach($plan['preparation']['rows']as $spec){$t=$spec['table'];$meta=$lane==='B'?$q('SELECT COLUMN_NAME,COLUMN_TYPE,IS_NULLABLE,COLUMN_DEFAULT,EXTRA,COLUMN_KEY FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=? ORDER BY ORDINAL_POSITION',['ydy_'.$t]):$q('SELECT COLUMN_NAME,DATA_TYPE,DATA_LENGTH,DATA_PRECISION,DATA_SCALE,NULLABLE,DATA_DEFAULT FROM USER_TAB_COLUMNS WHERE TABLE_NAME=? ORDER BY COLUMN_ID',[strtoupper('ydy_'.$t)]);if($meta!==$pre['metadata'][$t])throw new RuntimeException('Preparation metadata drift');foreach($meta as $column){$key=strtolower($column['column_name']);$required=($lane==='B'?$column['is_nullable']==='NO':$column['nullable']==='N')&&($lane==='B'?$column['column_default']===null:$column['data_default']===null);if($key!=='id'&&$required&&!array_key_exists($key,$spec['row']))throw new RuntimeException('Required column absent');}if($q('SELECT id FROM ydy_'.$t.' WHERE uuid=?',[$spec['row']['uuid']])!==[])throw new RuntimeException('Fixed UUID collision');if(!empty($pre['triggers'][$t]))throw new RuntimeException('Unreviewed trigger');}
$save('fixture-before.json',$before);$journal=[];$save('fixture-attempt.json',['started'=>true,'completed'=>false,'journal'=>[]]);
try{$db->beginTransaction();foreach($plan['preparation']['rows']as $spec){$fields=array_keys($spec['row']);$quote=$lane==='B'?'`':'"';$cols=array_map(static function($v)use($quote){return $quote.($quote==='"'?strtoupper($v):$v).$quote;},$fields);$sql='INSERT INTO ydy_'.$spec['table'].' ('.implode(',',$cols).') VALUES ('.implode(',',array_fill(0,count($fields),'?')).')';$s=$db->prepare($sql);$binds=[];foreach(array_values($spec['row'])as $i=>$v){$type=is_int($v)?PDO::PARAM_INT:PDO::PARAM_STR;$s->bindValue($i+1,$v,$type);$binds[]=['value'=>$v,'type'=>$type,'php_type'=>gettype($v)];}$event=['sql'=>$sql,'binds'=>$binds,'success'=>false];try{$event['success']=$s->execute();$event['rowCount']=$s->rowCount();$event['errorInfo']=$s->errorInfo();}finally{$journal[]=$event;$save('fixture-attempt.json',['started'=>true,'completed'=>false,'journal'=>$journal]);}if($event['rowCount']!==1)throw new RuntimeException('Preparation rowCount');}$db->commit();}catch(Throwable $e){if($db->inTransaction())$db->rollBack();$save('fixture-error.json',['class'=>get_class($e),'message'=>$e->getMessage(),'journal'=>$journal]);throw $e;}
$after=$source();$save('fixture-after.json',$after);$save('fixture-oracle.json',$GLOBALS['NF_ORACLE']);$save('fixture-attempt.json',['started'=>true,'completed'=>true,'committed'=>true,'journal'=>$journal]);echo json_encode(['lane'=>$lane,'prepared'=>count($journal),'committed'=>true]),"\n";
