<?php

declare(strict_types=1);

$mode=(string)($argv[1]??'');
$journalPath=(string)($argv[2]??'');
$self=(string)hash_file('sha256',__FILE__);
if(count($argv)!==3 || !in_array($mode,['--preflight','--recover'],true)
    || !preg_match('~^/tmp/cdx-rpe-c-[a-f0-9]{12}/recovery\.json$~D',$journalPath)
    ||($mode==='--recover'&&((string)getenv('CDX_RPE_RECOVER')!=='ROOT_RECOVER_RPE_C_V1'
        ||!hash_equals($self,(string)getenv('CDX_RPE_RECOVER_SHA'))))){
    echo json_encode(['status'=>'default_deny','connected'=>false,'dml'=>false]),PHP_EOL;exit(78);
}
if(!is_file($journalPath)||is_link($journalPath)||is_link(dirname($journalPath))
    ||(fileperms(dirname($journalPath))&0777)!==0700||(fileperms($journalPath)&0777)!==0600){
    throw new RuntimeException('Journal invalid');
}
$saved=json_decode((string)file_get_contents($journalPath),true);
if(!is_array($saved)||($saved['lane']??null)!=='C'
    ||($saved['state']??null)!=='unexpected_reference_retain'
    ||!preg_match('/^CDXRPE[A-F0-9]{12}$/D',(string)($saved['marker']??''))
    ||!is_array($saved['ids']??null)){throw new RuntimeException('Journal ownership invalid');}
$marker=(string)$saved['marker'];$ids=$saved['ids'];
foreach(['actor','staff','rpe','info']as$key)if((int)($ids[$key]??0)<=0)throw new RuntimeException('Journal ID invalid');
$actorUuid=$marker.'A';$staffUuid=$marker.'S';$rpeUuid=$marker.'R';
$db=new PDO('dm:host=127.0.0.1;port=5237;schema=ZHCT_APP',(string)getenv('POC_USER'),
    (string)getenv('POC_PASSWORD'),[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_CASE=>PDO::CASE_LOWER]);
if((string)$db->query("SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")->fetchColumn()!=='ZHCT_APP')
    throw new RuntimeException('Schema drift');
$count=static function(PDO $pdo,string$sql,array$args=[]):int{$s=$pdo->prepare($sql);$s->execute($args);return(int)$s->fetchColumn();};
$tables=static function(PDO $pdo,string$column):array{$s=$pdo->prepare('SELECT TABLE_NAME FROM USER_TAB_COLUMNS WHERE COLUMN_NAME=?');$s->execute([$column]);return$s->fetchAll(PDO::FETCH_COLUMN);};
$refs=static function(PDO $pdo,array$tables,string$column,string$value)use($count):array{$out=[];foreach($tables as$table){if(!preg_match('/^YDY_[A-Z0-9_]+$/D',(string)$table))throw new RuntimeException('Table invalid');$n=$count($pdo,'SELECT COUNT(*) FROM '.$table.' WHERE '.$column.'=?',[$value]);if($n)$out[(string)$table]=$n;}return$out;};
$ownership=[
    'actor'=>$count($db,'SELECT COUNT(*) FROM YDY_USER WHERE ID=? AND UUID=? AND ACCOUNT=? AND CREATE_BY=? AND TYPE=0 AND STATUS=0',[(int)$ids['actor'],$actorUuid,$actorUuid,$marker]),
    'staff'=>$count($db,'SELECT COUNT(*) FROM YDY_STAFF WHERE ID=? AND UUID=? AND PERSONNEL_UMBER=? AND CREATE_BY=? AND IS_SHOW=0 AND STATUS=0',[(int)$ids['staff'],$staffUuid,$marker,$marker]),
    'rpe'=>$count($db,'SELECT COUNT(*) FROM YDY_RPE WHERE ID=? AND UUID=? AND STAFF_UUID=? AND CREATE_BY=?',[(int)$ids['rpe'],$rpeUuid,$staffUuid,$actorUuid]),
    'info'=>$count($db,'SELECT COUNT(*) FROM YDY_RPE_INFO WHERE ID=? AND RPE_UUID=?',[(int)$ids['info'],$rpeUuid]),
];
$staffRefs=$refs($db,$tables($db,'STAFF_UUID'),'STAFF_UUID',$staffUuid);
$rpeRefs=$refs($db,$tables($db,'RPE_UUID'),'RPE_UUID',$rpeUuid);
$dateMenu=$count($db,'SELECT COUNT(*) FROM YDY_DATE_MENU WHERE STAFF_UUID=? AND MENU_DATE=?',[$staffUuid,'2001-01-02']);
$safe=$ownership===['actor'=>1,'staff'=>1,'rpe'=>1,'info'=>1]
    &&$staffRefs===['YDY_RPE'=>1]&&$rpeRefs===['YDY_RPE_INFO'=>1]&&$dateMenu===0;
if($mode==='--preflight'){
    echo json_encode(['status'=>$safe?'recover_ready':'recover_blocked','ownership'=>$ownership,
        'staff_refs'=>$staffRefs,'rpe_refs'=>$rpeRefs,'date_menu_rows'=>$dateMenu,'dml'=>false]),PHP_EOL;
    exit($safe?0:3);
}
if(!$safe)throw new RuntimeException('Recovery safety gate failed');
$db->beginTransaction();
try{
    $deletes=[
        ['DELETE FROM YDY_RPE_INFO WHERE ID=? AND RPE_UUID=?',[(int)$ids['info'],$rpeUuid]],
        ['DELETE FROM YDY_RPE WHERE ID=? AND UUID=? AND STAFF_UUID=? AND CREATE_BY=?',[(int)$ids['rpe'],$rpeUuid,$staffUuid,$actorUuid]],
        ['DELETE FROM YDY_STAFF WHERE ID=? AND UUID=? AND PERSONNEL_UMBER=? AND CREATE_BY=? AND IS_SHOW=0 AND STATUS=0',[(int)$ids['staff'],$staffUuid,$marker,$marker]],
        ['DELETE FROM YDY_USER WHERE ID=? AND UUID=? AND ACCOUNT=? AND CREATE_BY=? AND TYPE=0 AND STATUS=0',[(int)$ids['actor'],$actorUuid,$actorUuid,$marker]],
    ];
    foreach($deletes as$delete){$s=$db->prepare($delete[0]);$s->execute($delete[1]);if($s->rowCount()!==1)throw new RuntimeException('Affected row mismatch');}
    $db->commit();
}catch(Throwable$e){if($db->inTransaction())$db->rollBack();throw$e;}
$fresh=new PDO('dm:host=127.0.0.1;port=5237;schema=ZHCT_APP',(string)getenv('POC_USER'),
    (string)getenv('POC_PASSWORD'),[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_CASE=>PDO::CASE_LOWER]);
$zero=$refs($fresh,$tables($fresh,'STAFF_UUID'),'STAFF_UUID',$staffUuid)===[]
    &&$refs($fresh,$tables($fresh,'RPE_UUID'),'RPE_UUID',$rpeUuid)===[]
    &&$count($fresh,"SELECT COUNT(*) FROM YDY_USER WHERE UUID LIKE 'CDXRPE%' OR ACCOUNT LIKE 'CDXRPE%' OR CREATE_BY LIKE 'CDXRPE%'")===0
    &&$count($fresh,"SELECT COUNT(*) FROM YDY_STAFF WHERE UUID LIKE 'CDXRPE%' OR PERSONNEL_UMBER LIKE 'CDXRPE%' OR CREATE_BY LIKE 'CDXRPE%'")===0
    &&$count($fresh,"SELECT COUNT(*) FROM YDY_RPE WHERE UUID LIKE 'CDXRPE%' OR STAFF_UUID LIKE 'CDXRPE%' OR CREATE_BY LIKE 'CDXRPE%'")===0
    &&$count($fresh,"SELECT COUNT(*) FROM YDY_RPE_INFO WHERE RPE_UUID LIKE 'CDXRPE%'")===0;
if(!$zero)throw new RuntimeException('Recovery independent zero failed');
unlink($journalPath);rmdir(dirname($journalPath));
echo json_encode(['status'=>'recovered_independent_zero','marker_rows'=>0,
    'staff_references'=>0,'rpe_references'=>0,'private_journal_removed'=>true]),PHP_EOL;
