<?php
declare(strict_types=1);
ini_set('display_errors','0');ini_set('log_errors','0');error_reporting(E_ALL);
set_error_handler(function($severity){if(!(error_reporting()&$severity)){return false;}throw new ErrorException('Sanitized warning',0,$severity);});
$stage='preflight';$n=0;
function checkO($expected,$actual): void {global $n;++$n;if($expected!==$actual){throw new RuntimeException('Offline assertion '.$n);}}
function offlineFields(): array {$fields=[];foreach(virtualSchema()['columns'] as $col){$fields[$col['name']]=['name'=>$col['name'],'type'=>$col['native_type'],'notnull'=>false,'default'=>null,'primary'=>$col['name']==='id','autoinc'=>false];}return $fields;}
try{
    $framework=$argv[1]??'';$runtime=realpath($argv[2]??'');$src=realpath($argv[3]??'');
    if(!in_array($framework,['store','ai_api'],true)||!$runtime||strpos($runtime,'/private/tmp/cdx-offline-shadow-')!==0||$src!=='/Users/wiscourper/Documents/workspace/zhct/zhctproject/'.$framework||PHP_INT_SIZE!==8){throw new RuntimeException('Private offline gate');}
    // Actual OS sandbox gate before any framework code: a refused connection is not merely ECONNREFUSED.
    $errno=0;$message='';$socket=@stream_socket_client('tcp://127.0.0.1:9',$errno,$message,1);
    checkO(false,$socket);checkO(1,$errno);checkO(true,stripos($message,'not permitted')!==false);
    require __DIR__.'/ProjectionContract.php';require __DIR__.'/GiftContract.php';
    $stage='bootstrap';
    if($framework==='store'){
        define('ROOT_PATH',$runtime.'/');define('APP_PATH',$src.'/application/');define('RUNTIME_PATH',$runtime.'/runtime/');
        require $src.'/thinkphp/base.php';
        require __DIR__.'/OfflineStore.php';$connection=new OfflineStoreConnection(['database'=>'offline_contract','debug'=>false]);$modelClass=OfflineStoreModel::class;$floatClass=OfflineStoreFloatModel::class;
    }else{
        $loader=require $src.'/vendor/autoload.php';$loader->addPsr4('app\\',$src.'/app/');$loader->addPsr4('cores\\',$src.'/cores/');
        require __DIR__.'/OfflineAi.php';$connection=new OfflineAiConnection(['database'=>'offline_contract','prefix'=>'yoshop_','debug'=>false]);$manager=new OfflineAiManager($connection);$connection->setDb($manager);$modelClass=OfflineAiModel::class;$floatClass=OfflineAiFloatModel::class;
        $actualMeta=json_decode(file_get_contents(__DIR__.'/metadata_C_run.json'),true);checkO('pass',$actualMeta['report']['status']);
        foreach($actualMeta['report']['columns'] as $col){$connection->giftFields[$col['name']]=['name'=>$col['name'],'type'=>$col['native_type'],'notnull'=>$col['nullable']==='N','default'=>null,'primary'=>$col['name']==='log_id','autoinc'=>false];}
    }
    $stage='compile';$compiled=[];
    $matrix=[
        ['one',['s.wide_id'],['s.id'=>'ASC'],1,false],
        ['multi_alias',['s.wide_id'=>'order_id','s.amount'=>'money','s.id'],['s.id'=>'DESC'],1,false],
        ['page_two',['s.wide_id'=>'order_id','s.amount'=>'money','s.id'],['s.id'=>'DESC'],2,false],
        ['star',['*'],['s.id'=>'ASC'],1,true],
        ['qualified_star',['s.*'],['s.id'=>'ASC'],1,true],
        ['reserved_alias',['s.wide_id'=>'order'],['s.id'=>'ASC'],1,false],
    ];
    foreach($matrix as [$key,$fields,$order,$page,$star]){
        [$query,$options]=buildOfflineCase($connection,$fields,$order,$page);$projection=ProjectionContract::compile($options,virtualSchema(),$star);checkO(true,is_array($projection));
        $native=emitOffline($connection,$query,$options,'native',null);$template=emitOffline($connection,$query,$options,'sentinel',null);$projected=emitOffline($connection,$query,$options,'projected',$projection);
        checkO(1,substr_count($template['sql'],'__CDX_PROJECTION_SENTINEL__'));
        checkO(str_replace('__CDX_PROJECTION_SENTINEL__',$native['field_fragment'],$template['sql']),$native['sql']);
        checkO(str_replace('__CDX_PROJECTION_SENTINEL__',$projected['field_fragment'],$template['sql']),$projected['sql']);
        checkO($native['bind'],$projected['bind']);checkO($native['bind'],$template['bind']);checkO(['owned_min'=>[7,PDO::PARAM_INT],'owned_label'=>['离线"检查',PDO::PARAM_STR]],$native['bind']);
        $plan=new ShadowPlan(['sql'=>$projected['sql'],'names'=>$projection['names'],'visible'=>$projection['visible'],'restore'=>$projection['restore']]);checkO($projected['sql'],$plan->sql());
        $compiled[$key]=['native'=>$native,'projected'=>$projected,'plan_sql_sha256'=>$plan->sqlHash(),'projection'=>$projection];
    }
    checkO(true,$compiled['page_two']['projected']['sql']!==$compiled['multi_alias']['projected']['sql']);
    $stage='unsupported_native_unmodified';$unsupported=[];
    [$q,$baseOptions]=buildOfflineCase($connection,['s.wide_id'],['s.id'=>'ASC'],1);
    $raw=$framework==='store'?new \think\db\Expression('SUM(s.wide_id) AS total'):new \think\db\Raw('SUM(s.wide_id) AS total');
    foreach(['distinct'=>['distinct'=>true],'group'=>['group'=>'s.id'],'having'=>['having'=>'COUNT(*) > 0'],'raw_field'=>['field'=>[$raw]],'free_alias'=>['field'=>['s.wide_id AS free_alias']],'write_context'=>['operation'=>'selectInsert']] as $label=>$change){
        $opts=array_replace($baseOptions,$change);$before=emitOffline($connection,$q,$opts,'native',null);$caught=false;try{ProjectionContract::compile($opts,virtualSchema(),false);}catch(InvalidArgumentException $e){$caught=true;}checkO(true,$caught);
        $after=emitOffline($connection,$q,$opts,'native',null);checkO($before,$after);$unsupported[$label]=['status'=>'native_unmodified_not_fixed','sql_sha256'=>hash('sha256',$before['sql'])];
    }
    checkO(0,$connection->denied);
    $stage='guard_negative';$expectedDenied=0;
    foreach([function()use($connection){$connection->connect();},function()use($connection){$connection->query('SELECT 1');},function()use($connection){$connection->getFields('unexpected_real_table');}] as $f){$caught=false;try{$f();}catch(RuntimeException $e){$caught=true;}checkO(true,$caught);++$expectedDenied;}
    checkO($expectedDenied,$connection->denied);
    $stage='framework_hydrate';$rows=[
        ['wide_id'=>9007199254740993,'amount'=>'-12345678901234567890.123456789012345678','n'=>null],
        ['wide_id'=>PHP_INT_MAX,'amount'=>'0.000000000000000001','n'=>'1.20'],
        ['wide_id'=>'18446744073709551615','amount'=>'99999999999999999999.999999999999999999','n'=>null],
        ['wide_id'=>null,'amount'=>'0.000000000000000000','n'=>null],
    ];$hydrated=[];
    $star=$compiled['star'];$projection=$star['projection'];$starPlan=new ShadowPlan(['sql'=>$star['projected']['sql'],'names'=>$projection['names'],'visible'=>$projection['visible'],'restore'=>$projection['restore']]);
    foreach($rows as $row){
        $expected=['id'=>7,'wide_id'=>$row['wide_id'],'amount'=>$row['amount'],'ratio'=>1.25,'label'=>'007','n'=>$row['n']];
        $raw=[7,$row['wide_id']===null?null:(float)$row['wide_id'],(float)$row['amount'],1.25,'007',$row['n']===null?null:(float)$row['n'],$row['wide_id']===null?null:(string)$row['wide_id'],$row['amount'],$row['n']];
        $restored=$starPlan->shape($starPlan->restore($raw),PDO::FETCH_ASSOC);checkO($expected,$restored);
        $prototype=new $modelClass();$m=$prototype->newInstance($restored);checkO($expected,$m->getData());checkO($row['wide_id'],$m->getAttr('wide_id'));checkO($expected,$m->toArray());$json=json_encode($m->toArray(),JSON_PRESERVE_ZERO_FRACTION);checkO($expected,json_decode($json,true));$hydrated[]=$json;
    }
    $m=(new $floatClass())->newInstance(['wide_id'=>'9007199254740993']);checkO(true,is_float($m->getAttr('wide_id')));checkO(9007199254740992.0,$m->getAttr('wide_id'));
    $stage='actual_gift_model';$gift=null;$giftCompiled=null;
    if($framework==='ai_api'){
        require $src.'/vendor/topthink/framework/src/helper.php';require $src.'/app/common.php';
        $app=new \think\App($runtime);$app->instance('http',new class {public function getName(){return 'api';}});\think\App::$store_id=1930401010;
        // Real global helpers/context and unmodified real model, no overridden init/getter.
        $giftCompiled=compileGiftOffline($connection);checkO($giftCompiled['native']['bind'],$giftCompiled['projected']['bind']);$giftPrototype=new \app\api\model\user\GiftLog();$gift=[];
        foreach([9007199254740993,PHP_INT_MAX,'18446744073709551615',null] as $wide){
            $row=['log_id'=>7,'biz_order_id'=>$wide,'money'=>'1.20','balance_before'=>'0.00','balance_after'=>'1.20'];
            $raw=[7,$wide===null?null:(float)$wide,1.2,0.0,1.2,$wide===null?null:(string)$wide,'1.20','0.00','1.20'];$p=$giftCompiled['plan'];$restored=$p->shape($p->restore($raw),PDO::FETCH_ASSOC);checkO($row,$restored);
            $model=$giftPrototype->newInstance($restored);checkO($row,$model->getData());checkO($wide,$model->getAttr('biz_order_id'));checkO($row,$model->toArray());$gift[]=json_encode($model->toArray(),JSON_PRESERVE_ZERO_FRACTION);
        }
    }
    checkO($expectedDenied,$connection->denied);
    $sourceIdentity=[];$classes=[\think\db\Builder::class,\think\db\Query::class,\think\Model::class];
    if($framework==='ai_api'){$classes=array_merge($classes,[\app\common\database\DmBuilder::class,\app\api\model\user\GiftLog::class,\cores\BaseModel::class,\app\common\service\FixedScaleDecimalResponse::class]);}
    foreach($classes as $class){$path=(new ReflectionClass($class))->getFileName();if(strpos($path,$src.'/')!==0){throw new RuntimeException('Physical source identity gate');}$sourceIdentity[$class]=['file'=>substr($path,strlen($src)+1),'sha256'=>hash_file('sha256',$path)];}
    if($framework==='ai_api'){foreach(['app_name','getStoreId'] as $function){$path=(new ReflectionFunction($function))->getFileName();if($path!==$src.'/app/common.php'){throw new RuntimeException('Real context helper identity gate');}$sourceIdentity[$function]=['file'=>'app/common.php','sha256'=>hash_file('sha256',$path)];}}
    if($giftCompiled!==null){$giftCompiled['plan']=['sql_sha256'=>$giftCompiled['plan']->sqlHash()];}
    echo json_encode(['status'=>'pass','scope'=>'offline_virtual_contract_compile_and_hydrate_only','framework'=>$framework,'php'=>PHP_VERSION,'assertions'=>$n,'os_network_denied'=>true,'db_queries'=>0,'guard_negative_denials'=>$expectedDenied,'implicit_schema_provider_reads'=>$connection->schemaReads,'gift_schema_provider_reads'=>$connection->giftSchemaReads??0,'offline_connection_allocations'=>$manager->allocations??0,'actual_metadata_used'=>isset($actualMeta),'source_identity'=>$sourceIdentity,'compiled'=>$compiled,'unsupported'=>$unsupported,'thin_model_wire'=>$hydrated,'actual_gift_model_wire'=>$gift,'gift_candidate_not_executed'=>$giftCompiled,'float_cast_red_preserved'=>true,'cache_enabled'=>false,'http_increment'=>0,'p0_closed'=>false],JSON_UNESCAPED_SLASHES|JSON_PRESERVE_ZERO_FRACTION).PHP_EOL;
}catch(Throwable $e){$trace=[];foreach($e->getTrace() as $t){$trace[]=['file'=>basename($t['file']??''),'line'=>$t['line']??0,'function'=>($t['class']??'').($t['type']??'').($t['function']??'')];}echo json_encode(['status'=>'fail','stage'=>$stage,'assertions'=>$n,'class'=>get_class($e),'code'=>(string)$e->getCode(),'source_file'=>basename($e->getFile()),'source_line'=>$e->getLine(),'trace_no_arguments'=>$trace]).PHP_EOL;exit(1);}
