<?php
declare(strict_types=1);
require_once __DIR__.'/contract.php';
function catRows(PDO $db,string $scope,string $table,array $fields,string $where='',array $args=[],string $order='',int $limit=0):array{
    $source=smLoad('source-mysql-metadata-private.json')[$scope][$table];$types=[];foreach($source as $c){$types[strtolower($c['column_name'])]=$c;}$dm=getenv('SM7_LANE')==='C';$select=[];$aliases=[];foreach($fields as $field){$parts=preg_split('/\s+as\s+/i',$field);$name=$parts[0];$alias=$parts[1]??$name;if(!isset($types[$name])||!preg_match('/^[a-z][a-z0-9_]*$/D',$alias)){throw new RuntimeException('Frozen projection field');}$q=$dm?'"'.strtoupper($name).'"':'`'.$name.'`';$expr=$q;if($dm&&$types[$name]['data_type']==='decimal'){$expr='CAST('.$q.' AS VARCHAR(200))';}$select[]=$expr.' AS '.($dm?'"'.strtoupper($alias).'"':'`'.$alias.'`');$aliases[$alias]=$types[$name];}
    $prefix=$scope==='ai'?'yoshop_':'ydy_';$sql='SELECT '.implode(',',$select).' FROM '.$prefix.$table.($where!==''?' WHERE '.$where:'').($order!==''?' ORDER BY '.$order:'');if($limit){$sql=smTop($sql,$limit);}$rows=smRows($db,$sql,$args);if(count($rows)>100){throw new RuntimeException('Consumer set above 100');}
    if($dm){foreach($rows as &$row){foreach($row as $field=>&$value){$c=$aliases[$field];if($value===null){continue;}if($c['data_type']==='decimal'){if(!is_string($value)||!preg_match('/^-?\d+(?:\.\d+)?$/D',$value)){throw new RuntimeException('Exact decimal text missing');}$scale=(int)$c['numeric_scale'];$fixed=bcadd($value,'0',$scale);if(bccomp($fixed,$value,max($scale,strlen(strrchr($value,'.')?:'')))!==0){throw new RuntimeException('Target decimal outside source scale');}$value=$fixed;}elseif(in_array($c['data_type'],['datetime','timestamp'],true)&&(int)$c['datetime_precision']===0&&is_string($value)&&preg_match('/^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\.0+$/D',$value,$m)){$value=$m[1];}elseif($c['data_type']==='float'&&$c['numeric_scale']!==null&&is_numeric($value)){$value=round((float)$value,(int)$c['numeric_scale']);}}unset($value);}unset($row);}return $rows;
}
function catOss(PDO $db):array{$rows=catRows($db,'store','config',['id','config_key','config_value'],"status=1 AND config_key IN ('ossDisjunctor','ossHost','businessIdentify')",[],'id');$map=[];foreach($rows as $r){if(array_key_exists($r['config_key'],$map)){throw new RuntimeException('Ambiguous URL configuration');}$map[$r['config_key']]=$r['config_value'];}return ['rows'=>$rows,'prefix'=>($map['ossHost']??'').'/'.(!empty($map['ossDisjunctor'])?($map['businessIdentify']??'').'/':'')];}
function catUrl($path,string $prefix):string{return empty($path)?'':str_replace('\\','/',$prefix.$path);}
function catPaginator(array $rows,int $size,int $page):array{$total=count($rows);$last=(int)ceil($total/$size);return ['total'=>$total,'per_page'=>$size,'current_page'=>$page>$last?($last>0?$last:1):max(1,$page),'last_page'=>$last,'data'=>array_slice($rows,($page-1)*$size,$size)];}
function catSnapshot(PDO $db,array $case,array $boundary):array{
    $p=$case['params'];$kind=$case['kind'];$sets=['actor'=>catActor($db)];$body=[];
    if($kind==='dishes'){$rows=catRows($db,'store','dishes',['id','uuid','name','price','file_path','unit'],'is_del=1 AND category=? AND name LIKE ?',[$p['category'],'%'.trim($p['keyword']).'%'],'id ASC');$sets['dishes']=$rows;$units=catRows($db,'store','config_enum',['id','enum_key','enum_name'],'enum_type=3 AND is_delete=0',[],getenv('SM7_LANE')==='C'?'"ORDER" ASC':'`order` ASC');$sets['units']=$units;$units=array_column($units,'enum_name','enum_key');$oss=catOss($db);$sets['url_config']=$oss['rows'];foreach($rows as &$r){$r['file_url']=catUrl($r['file_path'],$oss['prefix']);$r['unit']=$units[$r['unit']]??'';}unset($r);$body=['code'=>0,'message'=>'查询成功','data'=>catPaginator($rows,5,(int)$p['page'])];
    }elseif($kind==='recognize'){$all=smRows($db,smTop('SELECT d.id,d.dishes_uuid,d.img_url,d.feature FROM ydy_dishes_recognize_img d JOIN ydy_dishes c ON c.uuid=d.dishes_uuid WHERE d.is_delete=0 AND c.is_del=1 ORDER BY d.id DESC',((int)$p['page'])*5));$rows=array_slice($all,((int)$p['page']-1)*5,5);$total=catCount($db,'SELECT COUNT(*) n FROM ydy_dishes_recognize_img d JOIN ydy_dishes c ON c.uuid=d.dishes_uuid WHERE d.is_delete=0 AND c.is_del=1');$sets['source_page']=$rows;$sets['total']=$total;$oss=catOss($db);$sets['url_config']=$oss['rows'];foreach($rows as &$r){$r['img_url']=catUrl($r['img_url'],$oss['prefix']);}unset($r);$body=['code'=>0,'message'=>'查询成功','data'=>['data'=>$rows,'total'=>$total,'page'=>(int)$p['page'],'page_size'=>5]];
    }elseif($kind==='orders'){$config=catRows($db,'store','config',['id','config_key','config_value'],"config_key='consume_order_restaurant' AND status=1");if(count($config)>1){throw new RuntimeException('Ambiguous order config');}$sets['order_config']=$config;$where='is_delete=0 AND bind_time>=? AND bind_time<=? AND meal_times=?';$args=[$p['meal_date'].' 00:00:00',$p['meal_date'].' 23:59:59',$p['meal_times']];if($config&&(string)$config[0]['config_value']==='1'){$equipment=catRows($db,'store','equipment',['id','code','name','restaurant_id','del_flag'],'code=? AND del_flag=0',[$p['equipment_code']]);if(count($equipment)!==1){throw new RuntimeException('Order device no longer unique');}$sets['scope_equipment']=$equipment;$where.=' AND restaurant_id=?';$args[]=$equipment[0]['restaurant_id'];}else{$where.=' AND equipment_code=?';$args[]=$p['equipment_code'];}
        $fields=['id','order_no','user_id','bind_time','meal_times','total_price','meal_number','pay_status','pay_time','pay_price','meal_date','equipment_code','source','order_status','cash as cash_payment','subsidy as subsidy_payment','gift as gift_payment','refund_amount','refund_status','cash_refund_amount','subsidy_refund_amount','gift_refund_amount','remain_balance'];$all=catRows($db,'store','meal_order',$fields,$where,$args,'id DESC');$sets['orders']=$all;$page=array_slice($all,0,15);$relations=[];foreach($page as &$r){$user=catRows($db,'store','user',['id','nickname','name','mobile'],'id=?',[$r['user_id']]);$equip=catRows($db,'store','equipment',['id','code','name'],'code=? AND del_flag=0',[$r['equipment_code']]);if(count($user)>1||count($equip)>1){throw new RuntimeException('Order relation ambiguous');}$relations[$r['id']]=['user'=>$user,'equipment'=>$equip];$r['user']=$user[0]??null;$r['equipment']=$equip[0]??null;$r['nickname']=$user[0]['name']??'';$r['equipment_name']=$equip[0]['name']??'';if((int)$r['pay_status']===10){$r['pay_time']='-';}$r['pay_amount']=bcsub($r['pay_price']??'0.00',$r['refund_amount']??'0.00',2);$r['gift_net_amount']=bcsub(sprintf('%.2f',(float)($r['gift_payment']??0)),sprintf('%.2f',(float)($r['gift_refund_amount']??0)),2);$r['abnormal_status']=$r['remain_balance']>=0?1:2;$r['source_txt']=\app\common\enum\order\OrderSource::mealOrderData()[$r['source']]['name']??'其他';}unset($r);$sets['relations']=$relations;$data=catPaginator($all,15,1);$data['data']=$page;$sums=[];foreach(['total_price','pay_price','refund_amount'] as $field){$sum=null;foreach($all as $r){$sum=bcadd($sum??'0',$r[$field],2);}$sums[$field]=$sum===null?0.0:(float)$sum;$data[$field]=$sums[$field];}$data['pay_amount']=bcsub((string)$data['pay_price'],(string)$data['refund_amount'],2);$body=['code'=>0,'message'=>'查询成功','data'=>$data];
    }elseif($kind==='card'){$card=catRows($db,'store','staff_card',['id','card_id','card_status','is_delete','staff_uuid'],'card_id=? AND card_status=1 AND is_delete=0',[$p['card_id']]);$sets['card']=$card;if(!$card){$body=['code'=>1,'message'=>'卡号不存在或者异常','data'=>[]];}else{if(count($card)!==1){throw new RuntimeException('Card no longer unique');}$staff=catRows($db,'store','staff',['uuid','identity_number'],'uuid=? AND is_show=1',[$card[0]['staff_uuid']]);$user=catRows($db,'store','user',['id','name','staff_uuid','ai_user_id','mobile'],'staff_uuid=? AND is_delete=0',[$card[0]['staff_uuid']]);if(count($staff)!==1||count($user)!==1){throw new RuntimeException('Card person/user source changed');}$sets['staff']=$staff;$sets['user']=$user;$ai=catAiPdo();$aiUsers=catRows($ai,'ai','user',['user_id','balance','gift_balance'],'user_id=? AND is_delete=0',[$user[0]['ai_user_id']]);$now=date('Y-m-d H:i:s');$subsidy=catRows($ai,'ai','user_subsidy',['id','user_id','money','expiration_start_time','expiration_end_time','is_delete'],'user_id=? AND is_delete=0 AND expiration_start_time<=? AND expiration_end_time>=?',[$user[0]['ai_user_id'],$now,$now],'id');$sets['ai_user']=$aiUsers;$sets['active_subsidy']=$subsidy;$sum='0.00';foreach($subsidy as $r){$sum=bcadd($sum,$r['money'],2);}$dep=smRows($db,'SELECT sd.staff_uuid,d.uuid department_uuid,d.name department_name,p.uuid parent_department_uuid,p.name parent_department_name FROM ydy_staff_department sd LEFT JOIN ydy_department d ON d.uuid=sd.department_uuid LEFT JOIN ydy_department p ON p.uuid=d.puuid WHERE sd.staff_uuid=?',[$staff[0]['uuid']]);if(count($dep)>1){throw new RuntimeException('Card first-department choice unspecified; keep this branch limited');}$sets['department']=$dep;$body=['code'=>0,'message'=>'查询成功','data'=>['card_id'=>$p['card_id'],'cash_balance'=>sprintf('%.2f',(float)($aiUsers[0]['balance']??0)),'subsidy_balance'=>sprintf('%.2f',(float)$sum),'gift_balance'=>sprintf('%.2f',(float)($aiUsers[0]['gift_balance']??0)),'mobile'=>(string)$user[0]['mobile'],'name'=>(string)$user[0]['name'],'identity_number'=>(string)$staff[0]['identity_number'],'department_name'=>(string)($dep[0]['department_name']??''),'parent_department_name'=>(string)($dep[0]['parent_department_name']??'')]];}
    }elseif($kind==='face'){$page=(int)$p['page'];$staff=catRows($db,'store','staff',['id','uuid','name','mobile','create_time','is_show'],'',[],'id ASC',$page*20);$staff=array_slice($staff,($page-1)*20,20);$total=catCount($db,'SELECT COUNT(*) n FROM ydy_staff');$sets['staff_page']=$staff;$sets['total']=$total;$images=[];$rows=[];foreach($staff as $r){$image=catRows($db,'store','hardware_img',['uuid','head_img','create_time','head_img_url'],'staff_uuid=? AND is_del=0',[$r['uuid']],'create_time DESC',2);if(count($image)>1&&$image[0]['create_time']===$image[1]['create_time']){throw new RuntimeException('Face latest-image tie; no arbitrary oracle');}$images[$r['uuid']]=$image;$url='';$created='';if($image){$url=(!empty($boundary['is_oss'])?$boundary['domain_name_oss']:$boundary['domain_name']).$image[0]['head_img_url'];$created=$image[0]['create_time'];}$rows[]=['id'=>$r['id'],'nickname'=>$r['name'],'mobile'=>$r['mobile'],'deleted'=>$r['is_show']==1?0:1,'imageUrl'=>$url,'createTime'=>$created,'updateTime'=>''];}$sets['images']=$images;$body=['resultCode'=>0,'resultMsg'=>'获取成功','resultObject'=>['totalNum'=>$total,'limit'=>20,'currentPage'=>(string)$p['page'],'totalPage'=>ceil($total/20),'data'=>$rows]];
    }elseif($kind==='rotation'){$station=catRows($db,'store','nutrition_station',['id','code','uuid','interval_time'],'code=?',[$p['device_code']]);$sets['station']=$station;if(!$station){$data=['time_interval'=>0,'device_code'=>5,'imgs'=>[]];}else{if(count($station)!==1){throw new RuntimeException('Station code ambiguous');}$annex=catRows($db,'store','annex',['id','master_uuid','file_path'],'master_uuid=?',[$station[0]['uuid']],'id ASC',15);$sets['annex']=$annex;$oss=catOss($db);$sets['url_config']=$oss['rows'];$imgs=[];foreach($annex as $r){$imgs[]=['img_url'=>str_replace('\\','/',$oss['prefix'].($r['file_path']??''))];}$data=['device_code'=>(string)$p['device_code'],'time_interval'=>$station[0]['interval_time'],'imgs'=>$imgs];}$body=['code'=>0,'message'=>'ok','data'=>$data];
    }else{throw new RuntimeException('Unknown frozen kind');}
    return ['body'=>json_decode(json_encode($body,JSON_UNESCAPED_UNICODE|JSON_THROW_ON_ERROR)),'source_sets'=>$sets,'source_digest'=>hash('sha256',serialize($sets))];
}
