<?php
/** 只读部署验收；不执行迁移、不清理缓存、不发送通知。 */
if(PHP_SAPI!=='cli')exit('CLI only');
$root=rtrim($argv[1]??dirname(__DIR__),'/\\');$failures=0;
function deploymentCheck($ok,$label){global $failures;echo ($ok?'PASS: ':'FAIL: ').$label.PHP_EOL;if(!$ok)$failures++;}
deploymentCheck(PHP_VERSION_ID>=70300,'PHP >= 7.3');
$manifest=$root.'/deploy/optimization-acdefg-sha256.json';
deploymentCheck(is_file($manifest),'release manifest exists');
if(is_file($manifest)){
    $data=json_decode(file_get_contents($manifest),true);
    deploymentCheck(is_array($data)&&isset($data['files']),'valid release manifest');
    foreach($data['files']??[] as $path=>$expected){
        $safe=is_string($path)&&!preg_match('~(^/|^[a-z]:|\.\.)~i',$path);
        deploymentCheck($safe&&is_file($root.'/'.$path)&&hash_equals($expected,hash_file('sha256',$root.'/'.$path)),'file '.$path);
    }
}
deploymentCheck(!is_file($root.'/app/mobile/controller/OmsTestIdentity.php'),'retired test identity controller removed');
deploymentCheck(!is_file($root.'/config/test_identity.php'),'retired test identity config removed');
try{
    require $root.'/vendor/autoload.php';$app=new \think\App($root.'/');$app->initialize();
    $name=config('database.default');$database=config('database.connections.'.$name.'.database');$prefix=config('database.connections.'.$name.'.prefix');
    deploymentCheck(in_array($database,['wxoms','oms'],true),'expected database environment ('.$database.')');
    if(!preg_match('/^[a-zA-Z0-9_]+$/D',$prefix))throw new RuntimeException('Invalid prefix');
    foreach(['auth','message','member_newcomer_exam','member_newcomer_score','kt_registration','kt_exam_job'] as $table){
        $rows=\think\facade\Db::query('SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA=? AND TABLE_NAME=?',[$database,$prefix.$table]);
        deploymentCheck(count($rows)===1,'required table '.$table);
    }
    $columns=array_column(\think\facade\Db::query("SHOW COLUMNS FROM `{$prefix}member_newcomer_score`"),null,'Field');
    deploymentCheck(isset($columns['submission_key'],$columns['submission_result']),'receipt columns installed');
    deploymentCheck(isset($columns['score'])&&preg_match('/^(decimal\(\d+,[1-9]\d*\)|float|double)/i',$columns['score']['Type']),'fractional score storage');
    $indexes=\think\facade\Db::query("SHOW INDEX FROM `{$prefix}member_newcomer_score`");$unique=false;
    foreach($indexes as $index)if($index['Key_name']==='newcomer_submission'&&(int)$index['Non_unique']===0&&$index['Column_name']==='submission_key')$unique=true;
    deploymentCheck($unique,'unique submission key installed');
    \think\facade\Cache::store('redis')->get('optimization-preflight:read-only');deploymentCheck(true,'Redis readable');
    if($database==='oms'){
        deploymentCheck(!$app->isDebug(),'production debug disabled');
    }
}catch(\Throwable $error){deploymentCheck(false,'environment check: '.get_class($error).' code='.$error->getCode());}
echo $failures?'DEPLOYMENT NOT VERIFIED'.PHP_EOL:'LOCAL/CLI CHECKS PASSED; HTTP and device acceptance still required'.PHP_EOL;
exit($failures?1:0);
