<?php
declare(strict_types=1);
require __DIR__.'/common.php';
try{
    $db=smPdo();$lane=getenv('SM7_LANE');$dm=$lane==='C';$source=getenv('SM7_ROOT');$sha=[];
    foreach(file(__DIR__.'/SOURCE_SHA256.txt',FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES) as $line){[$hash,$file]=preg_split('/\s+/',$line,2);$sha[$file]=hash_file('sha256',$source.'/'.$file);if($sha[$file]!==$hash){throw new RuntimeException('Frozen source drift '.$file);}}
    $cols=smRows($db,$dm?"SELECT COLUMN_NAME,DATA_TYPE,NULLABLE,DATA_DEFAULT FROM USER_TAB_COLUMNS WHERE TABLE_NAME='YDY_USER' ORDER BY COLUMN_ID":'SHOW COLUMNS FROM ydy_user');
    $fk=smRows($db,$dm?"SELECT CONSTRAINT_NAME FROM USER_CONSTRAINTS WHERE TABLE_NAME='YDY_USER' AND CONSTRAINT_TYPE='R'":"SELECT CONSTRAINT_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='ydy_user' AND REFERENCED_TABLE_NAME IS NOT NULL");
    $tr=smRows($db,$dm?"SELECT TRIGGER_NAME FROM USER_TRIGGERS WHERE TABLE_NAME='YDY_USER'":"SHOW TRIGGERS WHERE `Table`='ydy_user'");
    if($fk||$tr){throw new RuntimeException('Actor FK/trigger side-effect gate');}
    $allowed=['id','uuid','account','pwd','salt','name','type','status','create_time','create_by','is_delete'];
    foreach($cols as $c){$name=$dm?strtolower($c['column_name']):$c['field'];$nullable=$dm?$c['nullable']==='Y':$c['null']==='YES';$def=$dm?$c['data_default']:$c['default'];if(!$nullable&&$def===null&&!in_array($name,$allowed,true)){throw new RuntimeException('Missing required actor field '.$name);}}
    $userBefore=smUserDigest($db);$recipeSql="SELECT r.menu_date,r.meal_times,r.restaurant_id,d.category,COUNT(*) n FROM ydy_recipes r JOIN ydy_dishes d ON d.uuid=r.dishes_uuid WHERE d.status=1 AND d.is_del=1 AND d.category BETWEEN 1 AND 6 GROUP BY r.menu_date,r.meal_times,r.restaurant_id,d.category ORDER BY n DESC";
    $groups=smRows($db,smTop($recipeSql,40));$recipe=null;
    foreach($groups as $g){if((int)$g['n']<=100&&(int)$g['restaurant_id']>0){$staff=smRows($db,smTop('SELECT uuid,restaurant_id FROM ydy_staff WHERE restaurant_id=? AND is_show=1 ORDER BY id',1),[(int)$g['restaurant_id']]);if($staff){$recipe=['date'=>substr((string)$g['menu_date'],0,10),'meal'=>(int)$g['meal_times'],'restaurant'=>(int)$g['restaurant_id'],'category'=>(int)$g['category'],'staff_uuid'=>$staff[0]['uuid'],'joined_count'=>(int)$g['n']];break;}}}
    $hw=smRows($db,smTop('SELECT h.staff_uuid,h.menu_date,h.meal_times,COUNT(*) n FROM ydy_date_menu_hardware_img h JOIN ydy_initial_menu i ON i.hardware_img_uuid=h.uuid WHERE i.meal_type IN (1,4) GROUP BY h.staff_uuid,h.menu_date,h.meal_times ORDER BY n DESC',8));
    $check=smRows($db,smTop('SELECT i.staff_uuid,i.menu_date,i.meal_times,sd.department_uuid,COUNT(*) n FROM ydy_initial_menu i JOIN ydy_staff s ON s.uuid=i.staff_uuid JOIN ydy_staff_department sd ON sd.staff_uuid=s.uuid WHERE i.meal_type IN (1,4) GROUP BY i.staff_uuid,i.menu_date,i.meal_times,sd.department_uuid ORDER BY n DESC',8));
    $versions=smRows($db,smTop('SELECT * FROM ydy_equipment_version ORDER BY create_time DESC',5));$equip=smRows($db,smTop('SELECT id,code,name,restaurant_id,type FROM ydy_equipment WHERE del_flag=0 AND type IN (1,9,40,20,30,60) ORDER BY id',5));
    $out=['lane'=>$lane,'source_sha256'=>$sha,'user_columns'=>$cols,'user_fk'=>0,'user_triggers'=>0,'natural_user_before'=>$userBefore,'recipe'=>$recipe,'hardware'=>$hw[0]??null,'check'=>$check[0]??null,'versions'=>$versions,'equipment'=>$equip,'dml'=>0,'ddl'=>0];smSave('preflight-private.json',$out);
    echo json_encode(['status'=>'pass','lane'=>$lane,'actor_schema_ready'=>true,'recipe_count'=>$recipe['joined_count']??0,'hardware_source_available'=>(bool)$hw,'check_source_available'=>(bool)$check,'version_rows'=>count($versions),'consumer_equipment_rows'=>count($equip),'source_sha_verified'=>true,'dml'=>0]),PHP_EOL;
}catch(Throwable $e){smSave('preflight-error-private.json',['class'=>get_class($e),'message'=>$e->getMessage()]);echo json_encode(['status'=>'fail','class'=>get_class($e),'code'=>(string)$e->getCode(),'message_sha256'=>hash('sha256',$e->getMessage())]),PHP_EOL;exit(1);}
