<?php
declare(strict_types=1);
$base=$argv[1]??dirname(__DIR__,4).'/zhctproject/ai_api';$candidate=$argv[2]??$base;
define('TP_ENV','poc');define('BUSINESS','aizhct');define('ENTERPRISE_NO','10001');require $base.'/vendor/autoload.php';
spl_autoload_register(static function($c)use($base,$candidate){foreach(['app\\'=>'app/','cores\\'=>'cores/'] as $p=>$d)if(strpos($c,$p)===0){$r=$d.str_replace('\\','/',substr($c,strlen($p))).'.php';$f=is_file($candidate.'/'.$r)?$candidate.'/'.$r:$base.'/'.$r;if(is_file($f))require $f;}},true,true);
trait NoStaffIO{public static $IO=0;public function getFields(string $table):array{return ['height'=>['name'=>'height','type'=>'decimal(5,2)','notnull'=>true,'default'=>'0.00','primary'=>false,'autoinc'=>false],'weight'=>['name'=>'weight','type'=>'decimal(5,2)','notnull'=>true,'default'=>'0.00','primary'=>false,'autoinc'=>false]];}public function getPDOStatement(string $sql,array $bind=[],bool $master=false,bool $procedure=false):PDOStatement{self::$IO++;throw new RuntimeException('No SQL in response contract');}protected function createPdo($a,$b,$c,$d){self::$IO++;throw new RuntimeException('No PDO in response contract');}}
class StaffMysql extends \think\db\connector\Mysql{use NoStaffIO;public function getBuilderClass():string{return \think\db\builder\Mysql::class;}}
class StaffDm extends \app\common\database\Dm{use NoStaffIO;}
$app=new \think\App($base);$app->setEnvName('poc');$rt=sys_get_temp_dir().'/cdx-ai-staff-contract-'.getmypid().'/';mkdir($rt,0700,true);$app->setRuntimePath($rt);$app->initialize();\think\App::$store_id=2147001111;$cfg=$app->config->get('database');$mysql=$cfg['connections']['mysql'];$mysql['type']='\\StaffMysql';$dm=$mysql;$dm['type']='\\StaffDm';$cfg['connections']=['mysql'=>$mysql,'dm'=>$dm];$n=0;$fail=[];$must=static function($ok,$label)use(&$n,&$fail){$n++;if(!$ok)$fail[]=$label;};
$values=[[0,'0.00'],[170.5,'170.50'],[60.25,'60.25'],[0.1,'0.10'],[999.99,'999.99'],[null,null],['bad','bad'],['170.50','170.50'],['1e2','1e2'],[0.001,0.001],[1000,1000],[INF,INF]];
foreach(['mysql','dm'] as $engine){$cfg['default']=$engine==='mysql'?'dm':'mysql';$app->config->set($cfg,'database');$app->db->setConfig($app->config);$app->db->connect('mysql',true);$app->db->connect('dm',true);
 foreach(['app\\common\\model\\staff\\Staff','app\\store\\model\\staff\\Staff','app\\terminal\\model\\staff\\Staff'] as $class){
  foreach(['height','weight'] as $field)foreach($values as $i=>$pair){[$value,$expected]=$pair;$row=[$field=>$value,'other_number'=>0.123,'name'=>'CDX_UNIT','img'=>'unchanged'];$m=(new $class($row))->setConnection($engine);$before=serialize($m->getData());$want=$row;$want[$field]=$engine==='dm'?$expected:$value;$out=$m->toArray();$label=$engine.'/'.$class.'/'.$field.'/'.$i;$must($out===$want,$label.':DTO');$must(serialize($m->getData())===$before,$label.':getData unchanged');$must($m->getConnection()===$engine,$label.':explicit connection vs opposite default');if(!is_float($value)||is_finite($value))$must(json($out)->getContent()===json_encode($want,JSON_UNESCAPED_UNICODE),$label.':real Json');}
  $m=(new $class(['name'=>'CDX_UNIT']))->setConnection($engine);$must($m->toArray()===['name'=>'CDX_UNIT'],$engine.'/'.$class.':missing dimensions not added');
 }
}
$must(StaffMysql::$IO===0&&StaffDm::$IO===0,'No PDO/SQL/writes');echo json_encode(['assertions'=>$n,'failures'=>$fail,'actual_models'=>3,'actual_Json'=>true,'SQL'=>0,'PDO'=>0,'HTTP'=>0,'DML'=>0]),"\n";exit($fail?1:0);
