<?php
declare(strict_types=1);

// Shareable SELECT-only reproducer: no project controllers/models or private config files.
// Use a non-production DM instance and supply secrets through the process environment.
$phase='preflight';
try {
    $autoload=(string)getenv('DM_PROBE_AUTOLOAD');
    $mode=(string)getenv('DM_PROBE_MODE');
    if(!is_file($autoload)||!in_array($mode,['paired','default','stringify'],true)){
        throw new RuntimeException('Explicit public ORM autoloader and safe mode required');
    }
    foreach(['HOST','PORT','SCHEMA','USER','PASSWORD'] as $part){
        if((string)getenv('DM_PROBE_'.$part)===''){throw new RuntimeException('Test connection environment required');}
    }
    if($mode==='paired'&&!defined('PDO::EXTRA_DECIMAL')){throw new RuntimeException('Driver feature unavailable');}
    $phase='autoload';
    require $autoload;
    class PublicDmReproducerBuilder extends \think\db\Builder {}
    class PublicDmReproducerConnection extends \think\db\connector\Mysql
    {
        protected $params=[
            PDO::ATTR_CASE=>PDO::CASE_LOWER,
            PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_ORACLE_NULLS=>PDO::NULL_NATURAL,
            PDO::ATTR_STRINGIFY_FETCHES=>false,
            PDO::ATTR_EMULATE_PREPARES=>false,
        ];
        public function getBuilderClass(): string {return PublicDmReproducerBuilder::class;}
        protected function parseDsn(array $config): string {
            return 'dm:host='.$config['hostname'].';port='.$config['hostport'].';schema='.$config['database'];
        }
    }
    $params=[PDO::ATTR_STRINGIFY_FETCHES=>$mode!=='default',PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC];
    if($mode==='paired'){$params[PDO::EXTRA_DECIMAL]=1;}
    $manager=new \think\DbManager();
    $manager->setConfig(['default'=>'probe','connections'=>['probe'=>[
        'type'=>'\\'.PublicDmReproducerConnection::class,'hostname'=>getenv('DM_PROBE_HOST'),
        'hostport'=>(int)getenv('DM_PROBE_PORT'),'database'=>getenv('DM_PROBE_SCHEMA'),
        'username'=>getenv('DM_PROBE_USER'),'password'=>getenv('DM_PROBE_PASSWORD'),
        'prefix'=>'','debug'=>false,'params'=>$params,
    ]]]);
    $phase='connector-factory';
    $db=$manager->connect('probe');
    $sql="SELECT 7 AS I,CAST('9007199254740993.01' AS DECIMAL(30,2)) AS D,CAST('0.00' AS DECIMAL(5,2)) AS Z FROM DUAL";
    $table='('.$sql.') EXACT_Q';
    foreach(['query','find','select'] as $phase){
        fwrite(STDERR,'PUBLIC_ORM_BEGIN '.$phase.PHP_EOL);
        if($phase==='query'){$rows=$db->query($sql);}
        elseif($phase==='find'){$rows=$db->table($table)->where('i',7)->find();}
        else{$rows=$db->table($table)->select()->toArray();}
        $row=$phase==='find'?$rows:($rows[0]??[]);
        // Only types of synthetic values, never possible corrupt buffer contents.
        $types=[];foreach($row??[] as $name=>$value){$types[$name]=gettype($value);}
        fwrite(STDERR,'PUBLIC_ORM_DONE '.$phase.' '.json_encode($types).PHP_EOL);
    }
    echo json_encode(['status'=>'pass','mode'=>$mode,'php'=>PHP_VERSION,'business_writes'=>0]).PHP_EOL;
}catch(Throwable $e){
    echo json_encode(['status'=>'fail','phase'=>$phase,'class'=>get_class($e),'code'=>$e->getCode()]).PHP_EOL;
    exit(1);
}
