<?php

declare(strict_types=1);

// Read-only current DM PDO comparison: ATTR_STRINGIFY_FETCHES false/true.
// No exact numbers, dish/food names, IDs, dates or credentials are emitted.
$pid=(string)getenv('POC_RUNTIME_PID');
$modeArg=(string)getenv('CDX_DECIMAL_MODE');
if (!ctype_digit($pid) || !in_array($modeArg,['false','true'],true)) {
    fwrite(STDERR,"Approved C runtime PID and single mode required\n");
    exit(2);
}
function cdxDecimalShape($value): string
{
    if (!is_string($value)) return gettype($value);
    if (preg_match('/^[+-]?\d+$/',$value)) return 'digits.no_dp';
    if (preg_match('/^[+-]?\d+\.(\d+)$/',$value,$match)) {
        return 'digits.'.strlen($match[1]).'dp';
    }
    if (preg_match('/^[+-]?[\d.]+[Ee][+-]?\d+$/',$value)) {
        return 'scientific';
    }
    return 'other_string';
}
try {
    $cmdline=(string)file_get_contents('/proc/'.$pid.'/cmdline');
    if (strpos($cmdline,'127.0.0.1:18080')===false
        || strpos($cmdline,
            '/tmp/zhct-dm-poc-20260928.fcpiiN/store/public')===false) {
        throw new RuntimeException('Unexpected C runtime');
    }
    $env=array_fill_keys(['POC_HOST','POC_PORT','POC_SCHEMA',
        'POC_USER','POC_PASSWORD'],'');
    foreach (explode("\0",(string)file_get_contents('/proc/'.$pid.'/environ')) as $entry) {
        $pair=explode('=',$entry,2);
        if (count($pair)===2 && array_key_exists($pair[0],$env)) {
            $env[$pair[0]]=$pair[1];
        }
    }
    if ($env['POC_HOST']!=='127.0.0.1' || $env['POC_PORT']!=='5237'
        || strtoupper($env['POC_SCHEMA'])!=='ZHCT_APP'
        || strtoupper($env['POC_USER'])!=='ZHCT_APP'
        || $env['POC_PASSWORD']==='') {
        throw new RuntimeException('Unexpected C DB');
    }
    $open=static function (bool $stringify) use ($env): PDO {
        return new PDO('dm:host=127.0.0.1;port=5237;schema=ZHCT_APP',
            $env['POC_USER'],$env['POC_PASSWORD'],[
                PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,
                PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC,
                PDO::ATTR_STRINGIFY_FETCHES=>$stringify,
            ]);
    };
    $normal=$open(false);
    if (strtoupper((string)$normal->query(
        "SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")
        ->fetchColumn())!=='ZHCT_APP') {
        throw new RuntimeException('Unexpected schema');
    }
    $pairs=$normal->query('SELECT DISTINCT d.UUID D_UUID,f.ID F_ID'
        .' FROM YDY_DISHES d JOIN YDY_DISH c ON c.DISHES_UUID=d.UUID'
        .' JOIN YDY_FOODS_COMPOSITION f ON f.ID=c.COMPOSITION_ID'
        .' WHERE d.STATUS=1 AND d.IS_DEL=1 AND d.STORE_ID=10001')
        ->fetchAll(PDO::FETCH_ASSOC);
    $dishUuid='';
    $foodId=0;
    foreach ($pairs as $pair) {
        $uuid=(string)($pair['D_UUID']??$pair['d_uuid']??'');
        $id=(int)($pair['F_ID']??$pair['f_id']??0);
        if (substr(hash('sha256',$uuid),0,12)==='2a23c2721fd0'
            && substr(hash('sha256',(string)$id),0,12)==='766cb53c753b') {
            $dishUuid=$uuid;
            $foodId=$id;
            break;
        }
    }
    if ($dishUuid==='' || $foodId<=0) {
        throw new RuntimeException('Original anonymous C source absent');
    }
    $out=['source_hash_matched'=>true,'modes'=>[]];
    foreach ([$modeArg==='true'] as $stringify) {
        $db=$stringify?$open(true):$normal;
        $mode=['tables'=>[]];
        foreach (['YDY_DISHES'=>['UUID',$dishUuid],
            'YDY_FOODS_COMPOSITION'=>['ID',$foodId]] as $table=>$target) {
            $stmt=$db->prepare('SELECT COLUMN_NAME,DATA_SCALE FROM USER_TAB_COLUMNS'
                .' WHERE TABLE_NAME=? AND DATA_TYPE=? ORDER BY COLUMN_ID');
            $stmt->execute([$table,'DECIMAL']);
            $columns=$stmt->fetchAll(PDO::FETCH_ASSOC);
            if (!$columns) throw new RuntimeException('DECIMAL metadata absent');
            $names=[];
            $scales=[];
            foreach ($columns as $column) {
                $name=(string)($column['COLUMN_NAME']??$column['column_name']??'');
                $scale=(int)($column['DATA_SCALE']??$column['data_scale']??-1);
                if (!preg_match('/^[A-Z_][A-Z0-9_]*$/',$name)) {
                    throw new RuntimeException('Unsafe metadata identifier');
                }
                $names[]=$name;
                $scales[$scale]=($scales[$scale]??0)+1;
            }
            $query=$db->prepare('SELECT ID,'.implode(',',$names).' FROM '.$table
                .' WHERE '.$target[0].'=?');
            $query->execute([$target[1]]);
            $rows=$query->fetchAll(PDO::FETCH_ASSOC);
            if (count($rows)!==1) throw new RuntimeException('Anonymous row not unique');
            $row=array_change_key_case($rows[0],CASE_UPPER);
            $types=[];
            $shapes=[];
            foreach ($names as $name) {
                $value=$row[$name];
                $type=gettype($value);
                $types[$type]=($types[$type]??0)+1;
                $shape=cdxDecimalShape($value);
                $shapes[$shape]=($shapes[$shape]??0)+1;
            }
            $examples=[];
            foreach (['WEIGHT','ENERGY','PROTEIN','CARBOHYDRATE',
                'DIETARY_FIBER'] as $name) {
                if (!array_key_exists($name,$row)) continue;
                $value=$row[$name];
                $examples[$name]=['type'=>gettype($value),
                    'shape'=>cdxDecimalShape($value)];
            }
            $mode['tables'][$table]=[
                'decimal_columns'=>count($names),
                'declared_scale_distribution'=>$scales,
                'decimal_php_types'=>$types,
                'decimal_shapes'=>$shapes,
                'representative_shapes'=>$examples,
                'id_php_type'=>gettype($row['ID']),
            ];
        }
        $countStmt=$db->prepare('SELECT COUNT(*) AS N FROM YDY_DISHES WHERE UUID=?');
        $countStmt->execute([$dishUuid]);
        $mode['count_php_type']=gettype($countStmt->fetchColumn());
        $out['modes'][$stringify?'stringify_true':'stringify_false']=$mode;
    }
    echo json_encode($out,JSON_UNESCAPED_SLASHES).PHP_EOL;
} catch (Throwable $error) {
    echo json_encode(['status'=>'error','class'=>get_class($error),
        'code'=>$error->getCode()]).PHP_EOL;
    exit(1);
}
