<?php
declare(strict_types=1);
require __DIR__ . '/ExactStatement.php';
$assertions = 0;
function check($expected, $actual): void {
    global $assertions;
    ++$assertions;
    if ($expected !== $actual) { throw new RuntimeException('Assertion ' . $assertions); }
}
try {
    if (!defined('PDO::EXTRA_DECIMAL')) { throw new RuntimeException('Candidate feature missing'); }
    foreach (['HOST','PORT','SCHEMA','USER','PASSWORD'] as $key) {
        if ((string)getenv('POC_'.$key) === '') { throw new RuntimeException('Approved runtime missing'); }
    }
    $pdo = new PDO('dm:host='.getenv('POC_HOST').';port='.getenv('POC_PORT').';schema='.getenv('POC_SCHEMA'),getenv('POC_USER'),getenv('POC_PASSWORD'),[
        PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_STRINGIFY_FETCHES=>true,
        PDO::EXTRA_DECIMAL=>1,
        PDO::ATTR_EMULATE_PREPARES=>false,
        PDO::ATTR_CASE=>PDO::CASE_LOWER,
        PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC,
        PDO::ATTR_STATEMENT_CLASS=>[ExactStatement::class,[]],
    ]);
    $sql="SELECT 7 AS I,CAST('9007199254740993.01' AS DECIMAL(30,2)) AS D,CAST('1.20' AS DECIMAL(5,2)) AS MONEY,CAST('1700000000.123456' AS DECIMAL(16,6)) AS T,CAST(1.25 AS DOUBLE) AS F,NULL AS N FROM DUAL";
    $expected=['i'=>7,'d'=>'9007199254740993.01','money'=>'1.20','t'=>'1700000000.123456','f'=>1.25,'n'=>null];
    check($expected,$pdo->query($sql)->fetch());
    check(array_values($expected),$pdo->query($sql)->fetch(PDO::FETCH_NUM));
    $both=$pdo->query($sql)->fetch(PDO::FETCH_BOTH);
    foreach(array_values($expected) as $i=>$value){check($value,$both[$i]);}
    foreach($expected as $name=>$value){check($value,$both[$name]);}
    check([$expected],$pdo->query($sql)->fetchAll());
    check([7],$pdo->query($sql)->fetchAll(PDO::FETCH_COLUMN,0));
    check(['9007199254740993.01'],$pdo->query($sql)->fetchAll(PDO::FETCH_COLUMN,1));
    check([null],$pdo->query($sql)->fetchAll(PDO::FETCH_COLUMN,5));
    check('9007199254740993.01',$pdo->query($sql)->fetchColumn(1));
    $stmt=$pdo->prepare("SELECT CAST(? AS DECIMAL(30,2)) AS D FROM DUAL");
    $stmt->execute(['9007199254740993.01']);check('9007199254740993.01',$stmt->fetchColumn());
    check(false,$stmt->fetchColumn());
    $stmt->execute(['-1.2']);check(['d'=>'-1.20'],$stmt->fetch());
    $stmt=$pdo->query('SELECT 7 AS I FROM DUAL WHERE 1=0');check([],$stmt->fetchAll());
    check(['c'=>0,'s'=>null],$pdo->query('SELECT COUNT(*) AS C,SUM(7) AS S FROM DUAL WHERE 1=0')->fetch());
    check('18446744073709551615',$pdo->query("SELECT CAST('18446744073709551615' AS DECIMAL(20,0)) AS D FROM DUAL")->fetchColumn());
    $stmt=$pdo->query('SELECT 7 AS I FROM DUAL');$stmt->setFetchMode(PDO::FETCH_NUM);check([7],$stmt->fetch());
    $rejected=false;try{$pdo->query('SELECT 1 AS X,2 AS X FROM DUAL')->fetch();}catch(UnexpectedValueException $e){$rejected=true;}check(true,$rejected);
    check([1,2],$pdo->query('SELECT 1 AS X,2 AS X FROM DUAL')->fetch(PDO::FETCH_NUM));
    $rejected=false;try{$pdo->query('SELECT 7 AS I FROM DUAL')->fetchAll(PDO::FETCH_OBJ);}catch(InvalidArgumentException $e){$rejected=true;}check(true,$rejected);
    echo json_encode(['php'=>PHP_VERSION,'assertions'=>$assertions,'status'=>'pass']).PHP_EOL;
} catch(Throwable $e) {
    // Neither raw SQL values nor connection/exception messages are logged.
    echo json_encode(['php'=>PHP_VERSION,'assertions'=>$assertions,'status'=>'fail','class'=>get_class($e),'code'=>$e->getCode()]).PHP_EOL;
    exit(1);
}
