<?php
declare(strict_types=1);
// Test-only loopback exact GET allowlist. No business write action is reachable.
$path = parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH);
$allowed = [];
foreach (['api','store','terminal'] as $module) foreach (['all','tree'] as $action) $allowed['/'.$module.'/Region/'.$action]='GET';
$allowed['/terminal/goods.Spec/list']='GET';
$allowed['/store/goods.Spec/list']='GET';
$allowed['/__poc_boundary']='GET';
if (!isset($allowed[$path]) || $allowed[$path] !== ($_SERVER['REQUEST_METHOD'] ?? '')) {
    http_response_code(403); echo '{"pilot_denied":true}'; return;
}
$root = (string)getenv('PILOT_TARGET_ROOT');
$runtime = (string)getenv('PILOT_RUNTIME');
register_shutdown_function(static function()use($runtime):void{
    $e=error_get_last();
    if($e!==null && in_array($e['type'],[E_ERROR,E_PARSE,E_CORE_ERROR,E_COMPILE_ERROR],true)){
        file_put_contents($runtime.'/fatal-private.jsonl',json_encode(['type'=>$e['type'],
            'file'=>basename($e['file']),'line'=>$e['line'],'message_base64'=>base64_encode($e['message'])])."\n",FILE_APPEND|LOCK_EX);
        chmod($runtime.'/fatal-private.jsonl',0600);
    }
});
// TP6 multi-app uses entry basename to infer application; preserve normal index entry.
$_SERVER['SCRIPT_FILENAME'] = $root . '/public/index.php';
$_SERVER['SCRIPT_NAME'] = '/index.php'; $_SERVER['PHP_SELF'] = '/index.php';
define('TP_ENV', 'poc'); define('BUSINESS', 'aizhct'); define('ENTERPRISE_NO', '10001');
$loader = require $root . '/vendor/autoload.php';
$overlay = (string)getenv('TERMINAL_SOURCE_OVERLAY');
if (!is_file($overlay . '/app/terminal/controller/Region.php')) throw new RuntimeException('Private source overlay absent');
$loader->setPsr4('app\\', $overlay . '/app');
$loader->setPsr4('cores\\', $overlay . '/cores');
require $root . '/external_stubs.php';
if ($path === '/__poc_boundary') {
    header('Content-Type: application/json');
    echo json_encode(['external_stubs' => class_exists(\app\common\Serve::class, false)
        && class_exists(\app\common\UserApi::class, false), 'readonly_get_allowlist' => true]);
    return;
}
$scenario = $_SERVER['HTTP_X_PILOT_SCENARIO'] ?? '';
if (!preg_match('/^PILOT_AI_[A-Z0-9_]{1,60}$/D', $scenario)) {
    http_response_code(403); echo '{"pilot_denied":true}'; return;
}
require __DIR__ . '/SqlCoverageRecorder.php';
try {
$app = new \think\App($root);
$app->setEnvName('poc'); $app->setRuntimePath($runtime . '/runtime/'); $app->initialize();
$config = $app->config->get('database');
foreach ($config['connections'] as &$connection) {
    $connection['trigger_sql'] = true;
    // No application SQL logging: only the redacting structural listener below.
    $connection['debug'] = false;
} unset($connection);
$app->config->set($config, 'database');
$app->db->setConfig($app->config);
$app->config->set(['default' => 'file', 'stores' => ['file' => [
    'type' => 'File', 'path' => $runtime . '/cache/', 'prefix' => '', 'expire' => 0,
]]], 'cache');
$app->config->set(['close'=>true,'default'=>'file','channels'=>[
    'file'=>['type'=>'FileFormat','path'=>$runtime.'/logs/','close'=>true],
]], 'log');
$actualSource = dirname((new ReflectionClass(\app\api\controller\Enum::class))->getFileName(), 4);
$recorder = new SqlCoverageRecorder($runtime . '/ai_queries.jsonl', $actualSource, $scenario);
$classification = ['connection_events'=>0,'metadata_events'=>0,'unclassified_events'=>0];
$app->db->listen(static function($sql,$elapsed=null)use($recorder,&$classification,$runtime,$scenario):void{
    if(strpos((string)$sql,'CONNECT:')===0){++$classification['connection_events'];return;}
    if(preg_match('/^\s*(SHOW|DESCRIBE|EXPLAIN|SP_TABLEDEF)\b/i',(string)$sql)
        || preg_match('/^\s*CALL\s+SP_TABLEDEF\s*\(/i',(string)$sql)
        || preg_match('/^\s*SELECT\b.*\bFROM\s+USER_(TAB_COLUMNS|CONSTRAINTS|CONS_COLUMNS)\b/is',(string)$sql)) {
        ++$classification['metadata_events'];
        file_put_contents($runtime.'/ai_queries.jsonl',json_encode(['kind'=>'metadata_fingerprint',
            'scenario'=>$scenario,'fingerprint'=>SqlCoverageRecorder::fingerprint((string)$sql)['fingerprint']])."\n",FILE_APPEND|LOCK_EX);
    }
    elseif(SqlCoverageRecorder::fingerprint((string)$sql)['operation']==='other')++$classification['unclassified_events'];
    $recorder->observe($sql,$elapsed);
});
register_shutdown_function([$recorder, 'finish']);
register_shutdown_function(static function()use($runtime,$scenario,&$classification):void{
    file_put_contents($runtime.'/ai_queries.jsonl',json_encode(['kind'=>'listener_classification',
        'scenario'=>$scenario]+$classification)."\n",FILE_APPEND|LOCK_EX);
});
$http = $app->http;
$response = $http->run(); $response->send(); $http->end($response);
} catch (Throwable $error) {
    file_put_contents($runtime.'/caught-private.jsonl',json_encode(['class'=>get_class($error),
        'file'=>basename($error->getFile()),'line'=>$error->getLine(),'message_base64'=>base64_encode($error->getMessage())])."\n",FILE_APPEND|LOCK_EX);
    chmod($runtime.'/caught-private.jsonl',0600);
    http_response_code(500); header('Content-Type: application/json');
    echo json_encode(['pilot_bootstrap_error'=>get_class($error),
        'file'=>basename($error->getFile()),'line'=>$error->getLine()]);
}
