<?php
declare(strict_types=1);
require_once __DIR__.'/ShadowCore.php';

/** Entire source is code-owned synthetic DUAL only. No user SQL/table identifiers. */
function syntheticFixtures(): array
{
    $single=function(string $sql,string $kind,int $p,int $s,array $cases): array{
        $spec=['sql'=>$sql,'names'=>['value','dm_shadow_0'],'visible'=>[0],'restore'=>[0=>['shadow'=>1,'rule'=>['kind'=>$kind,'precision'=>$p,'scale'=>$s]]]];
        return ['plan'=>new ShadowPlan($spec),'cases'=>$cases];
    };
    $out=[];
    $out['decimal30_2']=$single('SELECT Q.V AS VALUE,CAST(Q.V AS VARCHAR(128)) AS DM_SHADOW_0 FROM (SELECT CAST(? AS DECIMAL(30,2)) AS V FROM DUAL) Q','decimal_text',30,2,[
        [null,null],['0','0.00'],['-0','0.00'],['1.2','1.20'],['-1.2','-1.20'],['9007199254740993.01','9007199254740993.01'],['-9007199254740993.01','-9007199254740993.01'],
    ]);
    $out['decimal20_0']=$single('SELECT Q.V AS VALUE,CAST(Q.V AS VARCHAR(128)) AS DM_SHADOW_0 FROM (SELECT CAST(? AS DECIMAL(20,0)) AS V FROM DUAL) Q','decimal_text',20,0,[
        [null,null],['0','0'],['9007199254740993','9007199254740993'],['9223372036854775807','9223372036854775807'],['-9223372036854775808','-9223372036854775808'],['18446744073709551615','18446744073709551615'],
    ]);
    $out['decimal16_6']=$single('SELECT Q.V AS VALUE,CAST(Q.V AS VARCHAR(128)) AS DM_SHADOW_0 FROM (SELECT CAST(? AS DECIMAL(16,6)) AS V FROM DUAL) Q','decimal_text',16,6,[
        ['1700000000.123456','1700000000.123456'],['0.000001','0.000001'],['-0.000001','-0.000001'],
    ]);
    $out['decimal38_18']=$single('SELECT Q.V AS VALUE,CAST(Q.V AS VARCHAR(128)) AS DM_SHADOW_0 FROM (SELECT CAST(? AS DECIMAL(38,18)) AS V FROM DUAL) Q','decimal_text',38,18,[
        ['-12345678901234567890.123456789012345678','-12345678901234567890.123456789012345678'],
        ['99999999999999999999.999999999999999999','99999999999999999999.999999999999999999'],
        ['-99999999999999999999.999999999999999999','-99999999999999999999.999999999999999999'],
        ['0.000000000000000001','0.000000000000000001'],
    ]);
    // Distinct SQL bytes explicitly bind the same native DEC type to different trusted semantics.
    $out['signed']=$single('SELECT Q_SIGNED.V AS VALUE,CAST(Q_SIGNED.V AS VARCHAR(128)) AS DM_SHADOW_0 FROM (SELECT CAST(? AS DECIMAL(20,0)) AS V FROM DUAL) Q_SIGNED','signed_integer',0,0,[
        ['0',0],['9007199254740993',9007199254740993],['9223372036854775807',PHP_INT_MAX],['-9223372036854775808',PHP_INT_MIN],
    ]);
    $out['unsigned']=$single('SELECT Q_UNSIGNED.V AS VALUE,CAST(Q_UNSIGNED.V AS VARCHAR(128)) AS DM_SHADOW_0 FROM (SELECT CAST(? AS DECIMAL(20,0)) AS V FROM DUAL) Q_UNSIGNED','unsigned_integer',0,0,[
        ['0',0],['9007199254740993',9007199254740993],['9223372036854775807',PHP_INT_MAX],['18446744073709551615','18446744073709551615'],
    ]);
    $pairRule=['kind'=>'decimal_text','precision'=>30,'scale'=>2];
    $pairSpec=['sql'=>'SELECT R.K,R.V,CAST(R.V AS VARCHAR(128)) AS DM_SHADOW_0 FROM (SELECT 1 AS K,CAST(? AS DECIMAL(30,2)) AS V FROM DUAL UNION ALL SELECT 2 AS K,CAST(? AS DECIMAL(30,2)) AS V FROM DUAL) R ORDER BY R.K','names'=>['k','v','dm_shadow_0'],'visible'=>[0,1],'restore'=>[1=>['shadow'=>2,'rule'=>$pairRule]]];
    $out['pair']=['plan'=>new ShadowPlan($pairSpec)];
    $empty=$pairSpec;$empty['sql']='SELECT R.K,R.V,CAST(R.V AS VARCHAR(128)) AS DM_SHADOW_0 FROM (SELECT 1 AS K,CAST(? AS DECIMAL(30,2)) AS V FROM DUAL UNION ALL SELECT 2 AS K,CAST(? AS DECIMAL(30,2)) AS V FROM DUAL) R WHERE 1=0 ORDER BY R.K';
    $out['empty']=['plan'=>new ShadowPlan($empty)];
    $mixed=['sql'=>"SELECT 7 AS I,Q.V AS V,CAST(1.25 AS DOUBLE) AS F,'007' AS TXT,NULL AS N,CAST(Q.V AS VARCHAR(128)) AS DM_SHADOW_0 FROM (SELECT CAST(? AS DECIMAL(30,2)) AS V FROM DUAL) Q",'names'=>['i','v','f','txt','n','dm_shadow_0'],'visible'=>[0,1,2,3,4],'restore'=>[1=>['shadow'=>5,'rule'=>$pairRule]]];
    $out['mixed']=['plan'=>new ShadowPlan($mixed)];
    $textPair=$pairSpec;$textPair['sql']='SELECT R.K,R.V,CAST(R.V AS VARCHAR(128)) AS DM_SHADOW_0 FROM (SELECT CAST(? AS VARCHAR(16)) AS K,CAST(? AS DECIMAL(30,2)) AS V FROM DUAL UNION ALL SELECT CAST(? AS VARCHAR(16)) AS K,CAST(? AS DECIMAL(30,2)) AS V FROM DUAL) R';
    $out['text_pair']=['plan'=>new ShadowPlan($textPair)];
    return $out;
}

/** Deliberately broken trusted contracts, each expected to fail closed. */
function syntheticRejections(): array
{
    $sqls=[
        'wrong_layout'=>"SELECT CAST(1 AS DECIMAL(3,2)) AS WRONG,CAST('1.00' AS VARCHAR(128)) AS DM_SHADOW_0 FROM DUAL",
        'nontext_helper'=>"SELECT CAST(1 AS DECIMAL(3,2)) AS VALUE,CAST(1 AS DECIMAL(3,2)) AS DM_SHADOW_0 FROM DUAL",
        'bad_text'=>"SELECT CAST(1 AS DECIMAL(3,2)) AS VALUE,CAST('abc' AS VARCHAR(128)) AS DM_SHADOW_0 FROM DUAL",
        'null_pair'=>"SELECT CAST(NULL AS DECIMAL(3,2)) AS VALUE,CAST('1.00' AS VARCHAR(128)) AS DM_SHADOW_0 FROM DUAL",
        'precision'=>"SELECT CAST(1 AS DECIMAL(3,2)) AS VALUE,CAST('1000.00' AS VARCHAR(128)) AS DM_SHADOW_0 FROM DUAL",
        'scale'=>"SELECT CAST(1 AS DECIMAL(3,2)) AS VALUE,CAST('1.001' AS VARCHAR(128)) AS DM_SHADOW_0 FROM DUAL",
        'exponent'=>"SELECT CAST(1 AS DECIMAL(3,2)) AS VALUE,CAST('1e4' AS VARCHAR(128)) AS DM_SHADOW_0 FROM DUAL",
    ];
    $out=[];foreach($sqls as $key=>$sql){$out[$key]=new ShadowPlan(['sql'=>$sql,'names'=>['value','dm_shadow_0'],'visible'=>[0],'restore'=>[0=>['shadow'=>1,'rule'=>['kind'=>'decimal_text','precision'=>3,'scale'=>2]]]]);}return $out;
}
