<?php
declare(strict_types=1);
$lane=getenv('ARE_LANE');$root=getenv('ARE_ROOT');$out=['lane'=>$lane,'database_writes'=>0,'routes'=>[]];$stage='config';
function rows(PDO $db,string $sql,array $params=[]):array{if(!preg_match('/^SELECT\b/i',$sql))throw new RuntimeException('SELECT only');$q=$db->prepare($sql);$q->execute($params);$out=[];while($v=$q->fetch(PDO::FETCH_ASSOC)){if(count($out)>2000)throw new RuntimeException('Cap');$v=array_change_key_case($v,CASE_LOWER);foreach($v as &$x)if(is_resource($x))$x=stream_get_contents($x);ksort($v);$out[]=$v;}return $out;}
function hashData($v){return hash('sha256',json_encode($v,JSON_UNESCAPED_UNICODE|JSON_INVALID_UTF8_SUBSTITUTE));}
function wireShape($v){if(is_object($v)){$o=[];foreach(get_object_vars($v) as $k=>$x)$o[$k]=wireShape($x);ksort($o);return ['kind'=>'object','fields'=>$o];}if(is_array($v)){$a=[];foreach($v as $x){$s=wireShape($x);$a[hashData($s)]=$s;}ksort($a);return ['kind'=>'array','element_shapes'=>array_values($a)];}return is_int($v)||is_float($v)?'number':gettype($v);}
try{
 if(!in_array($lane,['B','C'],true))throw new RuntimeException('Lane');$cfg=require $root.'/application/database.php';if(($cfg['prefix']??'')!=='ydy_')throw new RuntimeException('Prefix');
 if($lane==='B'){$local=require '/workspace/zhct/zhctproject/store/application/config/local/database.php';foreach(['hostname','database','username','password'] as $k)if(($cfg[$k]??null)!==($local[$k]??null))throw new RuntimeException('Not local');$dsn='mysql:host='.$cfg['hostname'].';port='.($cfg['hostport']?:3306).';dbname='.$cfg['database'].';charset=utf8mb4';}
 else{foreach(['hostname'=>'POC_HOST','hostport'=>'POC_PORT','database'=>'POC_SCHEMA','username'=>'POC_USER','password'=>'POC_PASSWORD'] as $k=>$e)if((string)$cfg[$k]!==getenv($e))throw new RuntimeException('DM config');if(getenv('POC_HOST')!=='127.0.0.1'||getenv('POC_PORT')!=='5237'||getenv('POC_SCHEMA')!=='ZHCT_APP')throw new RuntimeException('DM identity');$dsn='dm:host=127.0.0.1;port=5237;schema=ZHCT_APP';}
 $db=new PDO($dsn,$cfg['username'],$cfg['password'],[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_CASE=>PDO::CASE_LOWER]);$p=$lane==='B'?'ydy_':'YDY_';$base='http://127.0.0.1:'.($lane==='B'?18331:18332);$boundary=json_decode((string)file_get_contents($base.'/__poc_boundary'),true);if(!is_array($boundary)||($boundary['school_feature']??true)!==false||!$boundary['external_stubs'])throw new RuntimeException('Boundary');$out['boundary']=$boundary;
 foreach(['api/controller/DiningConfig.php'=>'c80749aa80aff6b0f38651ae2d0888d2db117b507a643a19b4a2d57cc8497d81','api/service/DiningConfig.php'=>'4cbc230c468932e78c1f30cc93938b5fd64736536ba98becba0a0f80e52bc5fc'] as $file=>$sha){if(!hash_equals($sha,hash_file('sha256',__DIR__.'/source/application/'.$file)))throw new RuntimeException('Source drift');$out['source_sha256'][$file]=$sha;}
 $admin=rows($db,'SELECT ID,UUID,TYPE FROM '.$p.'user WHERE ID=(SELECT MIN(ID) FROM '.$p.'user WHERE TYPE=0 AND IS_DELETE=0)');if(count($admin)!==1)throw new RuntimeException('Admin absent');$admin=$admin[0];require_once $root.'/application/base/Security.php';$token=\app\base\Security::encrypt(implode("\t",[(string)$admin['id'],(string)$admin['uuid'],'CDXARE10_READONLY','0','','','CDXARE10_READONLY']));
 $stage='source';$source=static function()use($db,$p):array{$areas=rows($db,'SELECT * FROM '.$p.'restaurant_area ORDER BY ID ASC');$uuids=array_values(array_unique(array_filter(array_column($areas,'school_uuid'))));$departments=$uuids?rows($db,'SELECT UUID,NAME FROM '.$p.'department WHERE UUID IN ('.implode(',',array_fill(0,count($uuids),'?')).') ORDER BY UUID ASC',$uuids):[];return ['areas'=>$areas,'shops'=>rows($db,'SELECT * FROM '.$p.'restaurant_shop ORDER BY ID ASC'),'departments'=>$departments];};$before=$source();$out['source_before']=hashData($before);$out['source_counts']=array_map('count',$before);$valid=array_values(array_filter($before['areas'],static function($a){return (int)$a['is_delete']===0;}));usort($valid,static function($a,$b){return (int)$b['id']<=>(int)$a['id'];});if(!$valid)throw new RuntimeException('No natural area');
 $school=[];foreach($before['departments'] as $d)$school[(string)$d['uuid']]=(string)$d['name'];$expectedRow=static function($row)use($before,$school){foreach(['id','status','order','is_delete'] as $key)if(isset($row[$key]))$row[$key]=(int)$row[$key];foreach(['create_time','update_time'] as $field)if(isset($row[$field])&&is_string($row[$field])&&preg_match('/^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\.\d{1,6}$/D',$row[$field],$m))$row[$field]=$m[1];$n=0;foreach($before['shops'] as $s)if((int)$s['is_delete']===0&&(int)$s['area_id']===$row['id'])$n++;$row['restaurant_count']=$n;$row['status_label']=$row['status']===1?'启用':'停用';$row['school_name']=$school[(string)($row['school_uuid']??'')]??'';return $row;};
 $cases=['list_page1'=>['areaList',['page'=>1,'page_size'=>5]],'list_page2'=>['areaList',['page'=>2,'page_size'=>5]],'list_lower_clamp'=>['areaList',['page'=>0,'page_size'=>0]],'list_name'=>['areaList',['page'=>1,'page_size'=>200,'name'=>(string)$valid[0]['name']]],'list_empty'=>['areaList',['page'=>1,'page_size'=>5,'name'=>'CDXARE10_NO_MATCH_1B93D807']],'options'=>['areaOptions',[]]];
 foreach($cases as $name=>$case){$stage=$name;$ctx=stream_context_create(['http'=>['method'=>'POST','header'=>"Content-Type: application/x-www-form-urlencoded\r\ntoken: ".$token."\r\n",'content'=>http_build_query($case[1]),'timeout'=>30,'ignore_errors'=>true]]);$raw=(string)file_get_contents($base.'/api/dining_config/'.$case[0],false,$ctx);$j=json_decode($raw,true);$wire=json_decode($raw);$record=['method'=>'POST','path'=>'/api/dining_config/'.$case[0],'status'=>(int)substr($http_response_header[0]??'',9,3),'code'=>$j['code']??null,'wire_shape'=>wireShape($wire),'wire_sha256'=>hash('sha256',$raw)];if(($j['code']??-1)!==0||$record['status']!==200)throw new RuntimeException('HTTP');$d=$j['data'];
  if($case[0]==='areaOptions'){$expected=[];$asc=$before['areas'];foreach($asc as $area)if((int)$area['is_delete']===0&&(int)$area['status']===1)$expected[]=['value'=>(int)$area['id'],'label'=>(string)$area['name'],'children'=>[]];$record['rows']=count($d);$record['complete_source_values_and_order']=$d===$expected;}
  else{$params=$case[1];$filtered=$valid;if(($params['name']??'')!=='')$filtered=array_values(array_filter($filtered,static function($x)use($params){return mb_stripos((string)$x['name'],$params['name'])!==false;}));$page=max(1,(int)$params['page']);$size=max(1,min((int)$params['page_size'],200));$lastPage=(int)ceil(count($filtered)/$size);$reportedPage=$page>$lastPage?($lastPage>0?$lastPage:1):$page;$expected=array_map($expectedRow,array_slice($filtered,($page-1)*$size,$size));$actual=$d['data'];foreach($actual as &$row)ksort($row);foreach($expected as &$row)ksort($row);unset($row);$record['rows']=count($actual);$record['total']=$d['total'];$record['all_field_values_match']=$actual===$expected;$record['pagination_match']=$d['total']===count($filtered)&&$d['current_page']===$reportedPage&&$d['per_page']===$size&&$d['last_page']===$lastPage;$record['field_count']=$expected?count($expected[0]):0;}
  $out['routes'][$name]=$record;
 }
 $after=$source();$out['source_unchanged']=hashData($after)===$out['source_before'];$out['failure']='';
}catch(Throwable $e){$out['failure']=['stage'=>$stage,'class'=>get_class($e),'message_sha12'=>substr(hash('sha256',$e->getMessage()),0,12)];}
echo json_encode($out,JSON_UNESCAPED_UNICODE|JSON_INVALID_UTF8_SUBSTITUTE),"\n";exit(empty($out['failure'])?0:2);
