<?php
// Only SELECT on exact retained marked fixtures and approved owner/actor records.
$lane=getenv('GP_LANE');$root=getenv('GP_ROOT');
$cfg=(static function($file){return require $file;})($root.'/application/database.php');
$connect=static function($ai)use($lane,$cfg){$c=$ai?$cfg['ai_zhct']:$cfg;foreach(['hostname','hostport','database','username','password']as $key)$c[$key]=$c[$key]??$cfg[$key];
 if($lane==='B'){$local=require '/workspace/zhct/zhctproject/store/application/config/local/database.php';$expected=$ai?$local['ai_zhct']:$local;foreach(['hostname','database','username','password']as $key)if((string)$c[$key]!==(string)($expected[$key]??$local[$key]))throw new RuntimeException('Not approved code local');$dsn='mysql:host='.$c['hostname'].';port='.($c['hostport']?:3306).';dbname='.$c['database'].';charset=utf8mb4';}
 else{$schema=$ai?'AIZHCT_APP':'ZHCT_APP';$port=$ai?'5238':'5237';if($c['hostname']!=='127.0.0.1'||(string)$c['hostport']!==$port||$c['database']!==$schema)throw new RuntimeException('Not approved DM scope');$dsn='dm:host=127.0.0.1;port='.$port.';schema='.$schema;}
 return new PDO($dsn,$c['username'],$c['password'],[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_CASE=>PDO::CASE_LOWER,PDO::ATTR_STRINGIFY_FETCHES=>false,PDO::ATTR_EMULATE_PREPARES=>false]);
};
$journal=[];$q=static function($db,$sql,$args=[])use(&$journal){if(!preg_match('/^SELECT\b/i',$sql))throw new RuntimeException('SELECT only');$item=['SQL'=>$sql,'bindings'=>$args];$s=$db->prepare($sql);foreach($args as $i=>$value)$s->bindValue($i+1,$value,PDO::PARAM_STR);try{$s->execute();$rows=$s->fetchAll(PDO::FETCH_ASSOC);if(count($rows)>100)throw new RuntimeException('Cap100');foreach($rows as &$row){$row=array_change_key_case($row,CASE_LOWER);foreach($row as &$v)if(is_resource($v))$v=stream_get_contents($v);unset($v);}unset($row);$item['ok']=true;$item['rows']=count($rows);$journal[]=$item;return $rows;}catch(Throwable $e){$item['ok']=false;$item['error']=$e->getMessage();$journal[]=$item;throw $e;}};
$metadata=static function($db,$table)use($q,$lane){return $lane==='B'?$q($db,'SELECT COLUMN_NAME,COLUMN_TYPE,DATA_TYPE,DATETIME_PRECISION,IS_NULLABLE,COLUMN_DEFAULT,EXTRA FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=? ORDER BY ORDINAL_POSITION',[$table]):$q($db,'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($table)]);};
$full=static function($db,$table,$where,$args)use($metadata,$q,$lane){$fields=[];foreach($metadata($db,$table)as $column){$n=$column['column_name'];if(!preg_match('/^[a-z_][a-z0-9_]*$/iD',$n))throw new RuntimeException('Column name');$quoted=$lane==='B'?'`'.$n.'`':'"'.strtoupper($n).'"';$fields[]='CAST('.$quoted.' AS '.($lane==='B'?'CHAR':'VARCHAR(4000)').') AS '.$quoted;}return $q($db,'SELECT '.implode(',',$fields).' FROM '.$table.' WHERE '.$where,$args);};
$ai=$connect(true);$store=$connect(false);$a=$lane==='B'?'yoshop_':'YOSHOP_';$s=$lane==='B'?'ydy_':'YDY_';$owner=$lane==='B'?'44641':'1827';$marker='CDXGW11B6A91C';
$out=['lane'=>$lane,'DML'=>0,'DDL'=>0,'HTTP'=>0,'php_timezone'=>date_default_timezone_get(),'fixture_epoch_formatted'=>date('Y-m-d H:i:s',978278400),'source_sha'=>$sourceSha];
$out['metadata']=$metadata($ai,$a.'user_gift_log');
$out['identity']=$lane==='B'?$q($ai,'SELECT DATABASE() AS DB,VERSION() AS VERSION,@@session.sql_mode AS SQL_MODE'):$q($ai,"SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') AS DB FROM DUAL");
$scope='STORE_ID=? AND USER_ID=? AND OPERATOR_ID=?';$bind=['10001',$owner,$marker];
$out['rows']=$full($ai,$a.'user_gift_log',$scope.' ORDER BY LOG_ID',$bind);
if($out['rows']!==$oldWide['generated_rows'])throw new RuntimeException('Existing marked5 differ from sealed wide final');
$out['native_create_time']=$q($ai,'SELECT LOG_ID,CREATE_TIME FROM '.$a.'user_gift_log WHERE '.$scope.' ORDER BY LOG_ID',$bind);
$out['owner_hashes']=[];
foreach([['store',$s.'staff','UUID=?',[$lease['staff']['uuid']],'staff_fullrow_sha256'],['store',$s.'user','ID=?',[$lease['store_user']['id']],'store_user_fullrow_sha256'],['ai',$a.'user','USER_ID=?',[$owner],'ai_user_fullrow_sha256'],['store',$s.'user','ID=?',[(string)$lease['actor']['id']],'actor_fullrow_sha256']]as $ref){$db=$ref[0]==='store'?$store:$ai;$hash=hash('sha256',json_encode($full($db,$ref[1],$ref[2],$ref[3])));$out['owner_hashes'][$ref[4]]=$hash;$expected=$ref[4]==='actor_fullrow_sha256'?$oldWide['actor_before']['fullrow_sha256']:$oldWide['owner_before'][$ref[4]];if($hash!==$expected)throw new RuntimeException('Approved owner/actor changed '.$ref[4]);}
$out['date_probes']=[];
foreach(['include'=>['2000-12-31','2001-01-02'],'exclude'=>['2001-01-02','2001-01-02'],'single_day'=>['2001-01-01','2001-01-01']]as $name=>$dates){
 $strings=[$dates[0].' 00:00:00',$dates[1].' 23:59:59'];$unix=[strtotime($strings[0]),strtotime($strings[1])];
 $sql='SELECT LOG_ID FROM '.$a.'user_gift_log WHERE '.$scope.' AND CREATE_TIME BETWEEN ? AND ? ORDER BY LOG_ID DESC';
 $out['date_probes'][$name]=['dates'=>$dates,'strings'=>$strings,'unix'=>$unix,'original_string_binding'=>$q($ai,$sql,array_merge($bind,$strings))];
 if($lane==='B')$out['date_probes'][$name]['int_column_unix_binding']=$q($ai,$sql,array_merge($bind,$unix));
}
$out['rows_after']=$full($ai,$a.'user_gift_log',$scope.' ORDER BY LOG_ID',$bind);if($out['rows_after']!==$out['rows'])throw new RuntimeException('Marked rows changed during read');
$out['journal']=$journal;$out['passed']=true;
echo json_encode($out,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE|JSON_PRESERVE_ZERO_FRACTION),"\n";
