<?php
declare(strict_types=1);
function analysisOriginalSnapshot(callable $read,int $tenant,int $staff,int $operator):array
{
    $all=$read('meal','store_id=? AND staff_id=? AND is_delete=0',[$tenant,$staff],'meal_time DESC');if(!$all)throw new RuntimeException('No natural meal');$last=$all[0];if(isset($all[1])&&$all[1]['meal_time']===$last['meal_time'])throw new RuntimeException('Ambiguous last meal');if((int)$last['is_loading']!==0)throw new RuntimeException('Last natural meal still loading');$date=$last['meal_date'];$meals=$read('meal','store_id=? AND staff_id=? AND meal_date=? AND is_delete=0',[$tenant,$staff,$date]);$times=[];foreach($meals as $m){if(isset($times[$m['meal_times']]))throw new RuntimeException('Ambiguous same-date meal times');$times[$m['meal_times']]=$m;}
    $infos=$read('meal_infos','store_id=? AND staff_id=? AND meal_date=? AND is_delete=0',[$tenant,$staff,$date]);$lastInfos=$read('meal_infos','store_id=? AND meal_id=? AND is_delete=0',[$tenant,$last['id']]);$ids=array_values(array_unique(array_column(array_merge($infos,$lastInfos),'dishes_id')));$dishes=$ids?$read('dishes','store_id=? AND id IN ('.implode(',',array_fill(0,count($ids),'?')).')',array_merge([$tenant],$ids)):[];
    $recommend=$read('meal_recommend','store_id=? AND staff_id=? AND meal_date=?',[$tenant,$staff,$date]);if(count($recommend)!==1)throw new RuntimeException('Ambiguous/missing natural recommendation without is_delete filter');$scores=$read('meal_score_subtable','store_id=? AND staff_id=? AND meal_date=? AND user_id=? AND is_delete=0',[$tenant,$staff,$date,$operator]);if($scores)throw new RuntimeException('Synthetic operator unexpectedly has natural scores');$cate=$read('dishes_cate','pid=0');$enum=$read('config_enum','enum_type=4 AND is_delete=0',[],getenv('POC_DIALECT')==='dm'?'"ORDER" ASC':'`order` ASC');$dietary=$read('dietary_recommend','store_id=?',[$tenant],'id ASC');return ['last'=>$last,'meals'=>$meals,'infos'=>$infos,'last_infos'=>$lastInfos,'dishes'=>$dishes,'recommend'=>$recommend[0],'scores'=>$scores,'categories'=>$cate,'cooking_enum'=>$enum,'dietary_recommend'=>$dietary];
}
function analysisOriginalOracle(array $s,string $action,int $type=1):array
{
    $div=static function($a,$b):float{return (float)$b==0?0.0:round((float)$a/(float)$b,2);};$meals=[];foreach($s['meals'] as $m)$meals[$m['meal_times']]=$m;$last=$s['last'];$time=$last['meal_times'];$current=$meals[$time];$rec=$s['recommend'];$ratioKey=[1=>'morning_ratio',2=>'noon_ratio',3=>'night_ratio'][$time];$mealRatio=$rec[$ratioKey]??0;$dishes=[];foreach($s['dishes'] as $d)$dishes[$d['id']]=$d;
    if($action==='supply'){$out=[];$prefix=[1=>'morning',2=>'noon',3=>'night'][$time];foreach(['energy'=>'power','carbohydrate'=>'carbohydrate_weight','protein'=>'protein_weight','fat'=>'fat_weight'] as $k=>$field){$a=$current[$k]??0;$r=$rec[$prefix.'_'.$field]??0;$v=$div($a,$r);$out[$k]=['reality'=>$a,'recommend'=>$r,'ratio'=>$v?round($v*100,2):0,'evaluate'=>0];}$cr=$div($out['carbohydrate']['reality']*4,$out['energy']['reality']);$pr=$div($out['protein']['reality']*4,$out['energy']['reality']);$ca=$cr?round($cr*100,2):0;$pro=$pr?round($pr*100,2):0;$fat=$ca&&$pro?round(100-($ca+$pro),2):0;$out['supply_ratio']=['carbohydrate'=>$ca,'protein'=>$pro,'fat'=>max(0,$fat),'evaluate'=>0];return $out;}
    if($action==='dishesType'){$cate=[];foreach($s['categories'] as $c)if($c['id']!==21)$cate[$c['id']]=['id'=>$c['id'],'name'=>$c['name'],'count'=>0];$currentInfos=array_values(array_filter($s['infos'],static function($i)use($time){return $i['meal_times']==$time;}));foreach($currentInfos as $i)if(isset($cate[$i['category']]))$cate[$i['category']]['count']++;$food=\app\common\enum\dishes\FoodCategory::data();foreach($food as &$f){unset($f['value']);$f['count']=array_sum(array_column($currentInfos,$f['field']));}unset($f);return ['dishes_category'=>array_values($cate),'food_category'=>$food,'meal_type'=>0,'recommend_morning'=>0,'is_loading'=>0];}
    if($action==='dietary'){$fields=\app\common\enum\dishes\MealsDietary::data();$recommend=[];foreach($s['dietary_recommend'] as $r)if($r['start_energy']<=$rec['recommend_power']&&$r['end_energy']>=$rec['recommend_power']){$recommend=$r;break;}foreach($fields as &$f){unset($f['value']);$v=$recommend[$f['field']]??0;$f['recommend_value']=round($v*$mealRatio,2);$f['actual_value']=$current[$f['field']];$f['ratio']=round($div($f['actual_value'],$f['recommend_value'])*100,2);$sum=array_sum(array_column($s['meals'],$f['field']));$f['accumulate']=round($div($sum,$v)*100,2);}unset($f);return ['meals_detary'=>$fields,'cz'=>[],'bz'=>[],'is_loading'=>0];}
    if($action==='vitamin'){$fields=$type===1?['va','vb1','vb2','vpp','vc','ve']:['potassium','sodium','calcium','magnesium','iron','zinc'];$out=['cz'=>[],'bz'=>[],'is_loading'=>0];foreach($fields as $field){$daily=$rec[$field]??0;$per=isset($rec[$field])?round($rec[$field]*$mealRatio,2):0;$out[$field]=['recommend'=>$daily,'actual'=>$current[$field]??0,'ratio'=>round($div($current[$field]??0,$per)*100,2),'accumulate'=>round($div(array_sum(array_column($s['meals'],$field)),$daily)*100,2)];}return $out;}
    if($action==='dietaryFiber'){$cate=[];foreach($s['categories'] as $c)$cate[$c['id']]=['id'=>$c['id'],'name'=>$c['name'],'actual'=>0];$byTime=[];$day=0;foreach($s['infos'] as $i){$byTime[$i['meal_times']][]=$i;$day+=$i['dietary_fiber'];}if(empty($byTime[$time]))throw new RuntimeException('Fiber current meal infos absent');$total=(string)array_sum(array_column($byTime[$time],'dietary_fiber'));$out=['dishes_cate'=>$cate,'total'=>$total,'day_ratio'=>round($div($day,25),2)*100,'current_ratio'=>round($div($total,round(25*$mealRatio,2)),2)*100,'recommend_values'=>0,'evaluate'=>0,'is_loading'=>0];foreach($byTime[$time] as $i)if(!empty($i['category'])&&isset($dishes[$i['dishes_id']])){if(!isset($out['dishes_cate'][$i['category']]))throw new RuntimeException('Fiber category absent from dictionary');$out['dishes_cate'][$i['category']]['actual']+=$i['dietary_fiber'];$out['dishes_cate'][$i['category']]['dishes'][]=['name'=>$dishes[$i['dishes_id']]['name'],'weight'=>$i['dietary_fiber']];}foreach($out['dishes_cate'] as &$c)$c['actual']=(string)$c['actual'];unset($c);$out['dishes_cate']=array_values($out['dishes_cate']);return $out;}
    if($action==='cookingMethod'){$out=['recommend_count'=>0,'recommend_ratio'=>0,'no_recommend_count'=>0,'no_recommend_ratio'=>0,'cooking_method'=>[],'evaluate'=>0,'recommend_method'=>[],'is_loading'=>0];$enum=[];foreach($s['cooking_enum'] as $e)$enum[$e['enum_key']]=$e;$n=count($s['infos']);if(!$n)return $out;foreach($s['infos'] as $i){if(!isset($dishes[$i['dishes_id']]))continue;$method=$dishes[$i['dishes_id']]['cook_method'];if(!isset($enum[$method]))throw new RuntimeException('Cooking enum absent');if(isset($out['cooking_method'][$method])){$out['cooking_method'][$method]['number']++;$out['cooking_method'][$method]['rotio']=round($div($out['cooking_method'][$method]['number'],$n)*100,2);}else $out['cooking_method'][$method]=['name'=>$enum[$method]['enum_name'],'number'=>1,'rotio'=>round($div(1,$n)*100,2)];$out[$enum[$method]['recommend']==1?'recommend_count':'no_recommend_count']++;}$out['recommend_ratio']=round($div($out['recommend_count'],$n),2)*100;$out['no_recommend_ratio']=round($div($out['no_recommend_count'],$n),2)*100;return $out;}
    throw new RuntimeException('Oracle unsupported action');
}
