<?php
declare(strict_types=1);
// Fresh SELECT-only preflight. It never boots the app or constructs business controllers.
$lane = $argv[1] ?? '';
if (!in_array($lane, ['B', 'C'], true)) exit(78);
$phase = $argv[2] ?? 'initial';
if (!in_array($phase, ['initial', 'relations', 'actors', 'lease'], true)) exit(78);
define('BUSINESS', '');
define('TP_ENV', 'local');
define('APP_PATH', $lane === 'B' ? '/workspace/zhct/zhctproject/store/application/' : '/tmp/zhct-dm-poc-20260928.fcpiiN/store/application/');
$cfg = (static function(string $path):array { return require $path; })(APP_PATH . 'database.php');
if ($lane === 'B') {
    $local = (static function(string $path):array { return require $path; })('/workspace/zhct/zhctproject/store/application/config/local/database.php');
    foreach (['hostname','database','username','password'] as $key) {
        if (($cfg[$key]??null) !== ($local[$key]??null)) throw new RuntimeException('Not code-local');
        if (($cfg['ai_zhct'][$key]??null) !== ($local['ai_zhct'][$key]??null)) throw new RuntimeException('Not code-local named AI');
    }
    if ($cfg['charset'] !== 'utf8' || (string)($cfg['hostport']?:3306)!=='3306' || !empty($cfg['params'])) throw new RuntimeException('Effective config drift');
}
$named = $cfg;
foreach (['database','prefix','hostname','hostport','username','password'] as $key) $named[$key]=$cfg['ai_zhct'][$key]??$cfg[$key];
$out = ['lane'=>$lane,'http'=>0,'dml'=>0,'ddl'=>0,'database_connections'=>0,'native_selects'=>[], 'datasets'=>[],'schema'=>[],'errors'=>[]];
$raw = $out;
foreach (['store'=>$cfg,'ai'=>$named] as $connection => $config) {
    try {
        if ($lane==='C' && ($config['hostname']!=='127.0.0.1' || (string)$config['hostport']!==($connection==='store'?'5237':'5238') || $config['database']!==($connection==='store'?'ZHCT_APP':'AIZHCT_APP'))) throw new RuntimeException('DM scope mismatch');
        $dsn = $lane==='B' ? 'mysql:host='.$config['hostname'].';port='.($config['hostport']?:3306).';dbname='.$config['database'].';charset='.$config['charset'] : 'dm:host='.$config['hostname'].';port='.$config['hostport'].';schema='.$config['database'];
        $options=[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_CASE=>PDO::CASE_LOWER];
        if ($lane==='B') { $options[PDO::ATTR_EMULATE_PREPARES]=false; $options[PDO::ATTR_STRINGIFY_FETCHES]=false; }
        $pdo=new PDO($dsn,$config['username'],$config['password'],$options);
        $out['database_connections']++;
        $query=static function(string $sql,array $binds=[]) use($pdo,&$out,$connection):array {
            if (!preg_match('/^SELECT\b/i',$sql) || preg_match('/\b(INTO|FOR\s+UPDATE|SLEEP|BENCHMARK|DBMS_LOCK)\b/i',$sql) || strpos($sql,';')!==false) throw new RuntimeException('Not safe SELECT');
            $entry=['connection'=>$connection,'sql'=>$sql,'binds'=>$binds,'success'=>false];
            try { $stmt=$pdo->prepare($sql);foreach($binds as $i=>$value)$stmt->bindValue($i+1,$value,is_int($value)?PDO::PARAM_INT:PDO::PARAM_STR);$stmt->execute();$rows=[];
                while($row=$stmt->fetch(PDO::FETCH_ASSOC)){ $row=array_change_key_case($row,CASE_LOWER);foreach($row as &$v)if(is_resource($v))$v=stream_get_contents($v);unset($v);$rows[]=$row;if(count($rows)>500)throw new RuntimeException('Read cap'); }
                $entry['success']=true;$entry['row_count']=$stmt->rowCount();$entry['rows_read']=count($rows);$out['native_selects'][]=$entry;return $rows;
            } catch(Throwable $e){$entry['error']=$e->getMessage();$out['native_selects'][]=$entry;throw $e;}
        };
        $identity=$lane==='B'?$query('SELECT VERSION() AS version,DATABASE() AS db,@@character_set_connection AS charset'):$query("SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') AS db FROM DUAL");
        if($lane==='B'&&strpos($identity[0]['version'],'5.6.')!==0)throw new RuntimeException('Not MySQL 5.6');
        if($lane==='C'&&$identity[0]['db']!==$config['database'])throw new RuntimeException('DM identity');
        $out['identities'][$connection]=['scope_verified'=>true,'charset'=>$lane==='B'?$identity[0]['charset']:'driver-default','version'=>$lane==='B'?$identity[0]['version']:'DM8'];
        if ($phase==='relations' || $phase==='actors' || $phase==='lease') {
            if ($connection==='ai') continue;
            if($phase==='actors'){$out['datasets']['operators']=$query('SELECT id,uuid,account,name,type,status,is_delete FROM ydy_user WHERE account LIKE ? AND type=? AND is_delete=? ORDER BY id',['CDX%',0,0]);continue;}
            if($phase==='lease'){
                $id=$lane==='B'?68280:23597;
                $out['datasets']['order']=$query('SELECT id,order_no,user_id,restaurant_id,refund_status,refund_amount,cash_refund_amount,subsidy_refund_amount,gift_refund_amount,is_delete FROM ydy_meal_order WHERE id=?',[$id]);
                $uid=$lane==='B'?97165:2628;
                $out['datasets']['user']=$query('SELECT id,uuid,account,name,staff_uuid,ai_user_id,balance,pay_money,type,status,is_delete FROM ydy_user WHERE id=? AND account LIKE ?',[$uid,'CDXPAY%']);
                $out['datasets']['restaurant']=$query('SELECT id,uuid,name,status,is_delete FROM ydy_restaurants WHERE id=?',[1]);
                $out['datasets']['operator']=$query('SELECT id,uuid,account,name,staff_uuid,type,status,is_delete FROM ydy_user WHERE id=? AND account LIKE ?',[$lane==='B'?97260:2791,'CDX%']);
                $out['datasets']['collision']=$query('SELECT id,supplement_no,meal_order_id FROM ydy_meal_order_supplement WHERE supplement_no=? OR meal_order_id=?',['CDXFL11E2F7',$id]);
                continue;
            }
            $out['datasets']['actors']=$query('SELECT id,uuid,staff_uuid,account,type,is_delete FROM ydy_user WHERE account LIKE ? ORDER BY id',['CDXPAY%']);
            $out['datasets']['orders']=$query('SELECT mo.id,mo.order_no,mo.user_id,mo.restaurant_id,mo.meal_date,mo.meal_times,mo.order_status,mo.refund_status,mo.is_delete FROM ydy_meal_order mo INNER JOIN ydy_user u ON u.id=mo.user_id WHERE u.account LIKE ? ORDER BY mo.id',['CDXPAY%']);
            $out['datasets']['restaurants']=$query('SELECT id,name,status,is_delete FROM ydy_restaurants WHERE name LIKE ? ORDER BY id',['CDX%']);
            if ($lane==='B') {
                $out['schema']['supplement_constraints']=$query('SELECT CONSTRAINT_NAME,CONSTRAINT_TYPE FROM information_schema.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=? ORDER BY CONSTRAINT_NAME',['ydy_meal_order_supplement']);
                $out['schema']['supplement_indexes']=$query('SELECT INDEX_NAME,NON_UNIQUE,SEQ_IN_INDEX,COLUMN_NAME FROM information_schema.STATISTICS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=? ORDER BY INDEX_NAME,SEQ_IN_INDEX',['ydy_meal_order_supplement']);
                $out['schema']['supplement_triggers']=$query('SELECT TRIGGER_NAME,ACTION_TIMING,EVENT_MANIPULATION,ACTION_STATEMENT FROM information_schema.TRIGGERS WHERE EVENT_OBJECT_SCHEMA=DATABASE() AND EVENT_OBJECT_TABLE=? ORDER BY TRIGGER_NAME',['ydy_meal_order_supplement']);
            } else {
                $out['schema']['supplement_constraints']=$query('SELECT CONSTRAINT_NAME,CONSTRAINT_TYPE,STATUS,SEARCH_CONDITION FROM USER_CONSTRAINTS WHERE TABLE_NAME=? ORDER BY CONSTRAINT_NAME',['YDY_MEAL_ORDER_SUPPLEMENT']);
                $out['schema']['supplement_constraint_cols']=$query('SELECT CONSTRAINT_NAME,COLUMN_NAME,POSITION FROM USER_CONS_COLUMNS WHERE TABLE_NAME=? ORDER BY CONSTRAINT_NAME,POSITION',['YDY_MEAL_ORDER_SUPPLEMENT']);
                $out['schema']['supplement_indexes']=$query('SELECT INDEX_NAME,UNIQUENESS,INDEX_TYPE FROM USER_INDEXES WHERE TABLE_NAME=? ORDER BY INDEX_NAME',['YDY_MEAL_ORDER_SUPPLEMENT']);
                $out['schema']['supplement_index_cols']=$query('SELECT INDEX_NAME,COLUMN_NAME,COLUMN_POSITION FROM USER_IND_COLUMNS WHERE TABLE_NAME=? ORDER BY INDEX_NAME,COLUMN_POSITION',['YDY_MEAL_ORDER_SUPPLEMENT']);
                $out['schema']['supplement_triggers']=$query('SELECT * FROM USER_TRIGGERS WHERE TABLE_NAME=? ORDER BY TRIGGER_NAME',['YDY_MEAL_ORDER_SUPPLEMENT']);
            }
            continue;
        }
        $tables=$connection==='store'?['billing_record','billing_record_detail','meal_order_supplement','meal_order','user','staff','restaurants','equipment']:['cash_refund_order','cash_refund_order_log'];
        foreach($tables as $name){$table=($connection==='store'?'ydy_':'yoshop_').$name;
            $meta=$lane==='B'?$query('SELECT COLUMN_NAME,COLUMN_TYPE,IS_NULLABLE,COLUMN_DEFAULT,EXTRA FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=? ORDER BY ORDINAL_POSITION',[$table]):$query('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)]);
            $out['schema'][$connection][$name]=$meta;
            if(!$meta){$out['datasets'][$name]=['status'=>'table-absent'];continue;}
            if($name==='billing_record')$sql='SELECT id,bill_no,bill_month,staff_uuid,amount,status,is_delete,store_id FROM '.$table.' WHERE store_id=? AND (student_name LIKE ? OR staff_uuid LIKE ?) ORDER BY id';
            elseif($name==='meal_order_supplement')$sql='SELECT id,supplement_no,meal_order_id,user_id,restaurant_id,department_uuid,equipment_code,marketing_strategy_id,is_delete,store_id FROM '.$table.' WHERE store_id=? AND (supplement_no LIKE ? OR reason LIKE ?) ORDER BY id';
            elseif($name==='cash_refund_order')$sql='SELECT id,refund_no,staff_uuid,refund_amount,status,is_delete,store_id FROM '.$table.' WHERE store_id=? AND (staff_name LIKE ? OR remark LIKE ?) ORDER BY id';
            else continue;
            try{$rows=$query($sql,[10001,'CDX%','CDX%']);$raw['datasets'][$name]=$rows;$out['datasets'][$name]=['status'=>'marked-only','row_count'=>count($rows),'sha256'=>hash('sha256',serialize($rows)),'rows'=>$rows];}
            catch(Throwable $e){$out['errors'][]=['connection'=>$connection,'table'=>$name,'error'=>$e->getMessage()];}
        }
    } catch(Throwable $e){$out['errors'][]=['connection'=>$connection,'error'=>$e->getMessage()];}
}
$raw['report']=$out;
if(!is_dir(__DIR__.'/private'))mkdir(__DIR__.'/private',0700);
chmod(__DIR__.'/private',0700);
$file='preflight-'.($phase!=='initial'?$phase.'-':'').$lane.'.json';
file_put_contents(__DIR__.'/private/'.$file,json_encode($raw,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE));chmod(__DIR__.'/private/'.$file,0600);
// Native rows are only pre-approved synthetic CDX markers; connection credentials never serialized.
file_put_contents(__DIR__.'/'.$file,json_encode($out,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE));
echo json_encode(['lane'=>$lane,'http'=>0,'dml'=>0,'ddl'=>0,'database_connections'=>$out['database_connections'],'selects'=>count($out['native_selects']),'datasets'=>$out['datasets'],'errors'=>$out['errors']],JSON_UNESCAPED_UNICODE),"\n";
