<?php

declare(strict_types=1);

// One approved B fixture only: inspect exact ownership, optionally delete
// exact owned rows, then independently verify zero. No business-table DML.
if ($argc!==2 || !in_array($argv[1],
    ['--inspect-exact','--cleanup-exact'],true)) {
    fwrite(STDERR,"Explicit exact fixture inspection/cleanup flag required\n");
    exit(2);
}
$mode=$argv[1];
$marker=(string)getenv('CDXPARBILL_MARKER');
if ($marker!=='CDXPARBILL704E1721') {
    fwrite(STDERR,"This script is pinned to the one B fixture marker\n");
    exit(2);
}
$phase='manifest';
try {
    $path='/tmp/zhct-store-ab-bill4-20261002/B-'.$marker.'.json';
    if (!is_file($path) || (fileperms($path)&0777)!==0600) {
        throw new RuntimeException('Private manifest missing or mode wrong');
    }
    $manifest=json_decode((string)file_get_contents($path),true);
    if (!is_array($manifest) || ($manifest['lane']??'')!=='B'
        || ($manifest['marker']??'')!==$marker
        || ($manifest['business_tables_written']??null)!==false) {
        throw new RuntimeException('Manifest ownership/route mismatch');
    }
    $userUuid=(string)($manifest['user_uuid']??'');
    $roleUuid=(string)($manifest['role_uuid']??'');
    $menuUuid=(string)($manifest['menu_uuid']??'');
    $restaurantUuid=(string)($manifest['restaurant_uuid']??'');
    foreach ([$userUuid,$roleUuid,$menuUuid,$restaurantUuid] as $uuid) {
        if (!preg_match('/^[a-fA-F0-9-]{36}$/',$uuid)) {
            throw new RuntimeException('Manifest UUID invalid');
        }
    }
    $phase='local-db-boundary';
    $root='/tmp/zhct-http-store-mysql.dQTTBP';
    $cmd=str_replace("\0",' ',(string)file_get_contents('/proc/10001/cmdline'));
    if (strpos($cmd,' -S 127.0.0.1:18081 ')===false
        || strpos($cmd,$root.'/public')===false) {
        throw new RuntimeException('Wrong B runtime');
    }
    $load=static function(string $file): array { return require $file; };
    $local=$load('/workspace/zhct/zhctproject/store/application/config/local/database.php');
    $runtime=$load($root.'/application/database.php');
    foreach (['hostname','database','username','password'] as $key) {
        if (!isset($local[$key],$runtime[$key])
            || $local[$key]!==$runtime[$key]) {
            throw new RuntimeException('Wrong code-local development MySQL');
        }
    }
    if (($runtime['type']??null)!=='mysql'
        || (int)($runtime['hostport']??3306)
            !==(int)($local['hostport']??3306)) {
        throw new RuntimeException('Wrong MySQL dialect/port');
    }
    $open=static function() use ($local): PDO {
        return new PDO('mysql:host='.$local['hostname'].';port='.
            (int)($local['hostport']??3306).';dbname='.$local['database']
            .';charset=utf8mb4',(string)$local['username'],
            (string)$local['password'],[
                PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,
                PDO::ATTR_EMULATE_PREPARES=>false,
                PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC,
                PDO::ATTR_TIMEOUT=>8,
            ]);
    };
    $db=$open();
    if (strpos((string)$db->query('SELECT VERSION()')->fetchColumn(),'5.6.')!==0) {
        throw new RuntimeException('Not development MySQL5.6');
    }
    $count=static function(PDO $conn,string $sql,array $args=[]): int {
        $stmt=$conn->prepare($sql);
        $stmt->execute($args);
        return (int)$stmt->fetchColumn();
    };
    $scope=[
        'user'=>['ydy_user','uuid=?','uuid=? AND account=?',
            [$userUuid],[$userUuid,$marker]],
        'role'=>['ydy_role','uuid=?','uuid=? AND name=?',
            [$roleUuid],[$roleUuid,$marker]],
        'user_role'=>['ydy_user_role','user_uuid=?',
            'user_uuid=? AND role_uuid=? AND create_by=?',
            [$userUuid],[$userUuid,$roleUuid,$marker]],
        'role_menu'=>['ydy_role_menu','role_uuid=?',
            'role_uuid=? AND menu_uuid=? AND create_by=?',
            [$roleUuid],[$roleUuid,$menuUuid,$marker]],
        'user_data'=>['ydy_user_data','user_uuid=?',
            'user_uuid=? AND data_uuid=? AND type=3',
            [$userUuid],[$userUuid,$restaurantUuid]],
    ];
    $phase='ownership-counts';
    $counts=[];
    $unknown=false;
    foreach ($scope as $name=>[$table,$allWhere,$oursWhere,$allArgs,$ourArgs]) {
        $all=$count($db,'SELECT COUNT(*) FROM '.$table
            .' WHERE '.$allWhere,$allArgs);
        $ours=$count($db,'SELECT COUNT(*) FROM '.$table
            .' WHERE '.$oursWhere,$ourArgs);
        $counts[$name]=['scope'=>$all,'exact_owned'=>$ours];
        if ($all!==$ours || $ours>1) $unknown=true;
    }
    $markerWide=[
        'user_account'=>$count($db,'SELECT COUNT(*) FROM ydy_user'
            .' WHERE account=?',[$marker]),
        'role_name'=>$count($db,'SELECT COUNT(*) FROM ydy_role'
            .' WHERE name=?',[$marker]),
        'user_role_create_by'=>$count($db,'SELECT COUNT(*) FROM ydy_user_role'
            .' WHERE create_by=?',[$marker]),
        'role_menu_create_by'=>$count($db,'SELECT COUNT(*) FROM ydy_role_menu'
            .' WHERE create_by=?',[$marker]),
    ];
    if ($markerWide['user_account']!==$counts['user']['exact_owned']
        || $markerWide['role_name']!==$counts['role']['exact_owned']
        || $markerWide['user_role_create_by']!==$counts['user_role']['exact_owned']
        || $markerWide['role_menu_create_by']!==$counts['role_menu']['exact_owned']) {
        $unknown=true;
    }
    if ($mode==='--inspect-exact') {
        echo json_encode(['mode'=>'inspect','marker'=>$marker,
            'counts'=>$counts,'marker_counts'=>$markerWide,
            'unknown_association'=>$unknown],JSON_UNESCAPED_SLASHES).PHP_EOL;
        if ($unknown) exit(1);
        exit(0);
    }
    if ($unknown) throw new RuntimeException('Unknown relation: refuse delete');
    $phase='exact-delete';
    $delete=static function(PDO $conn,string $table,
        string $where,array $args): void {
        $stmt=$conn->prepare('DELETE FROM '.$table.' WHERE '.$where);
        $stmt->execute($args);
    };
    foreach (['role_menu','user_role','user_data','role','user'] as $name) {
        [$table,$allWhere,$oursWhere,$allArgs,$ourArgs]=$scope[$name];
        $delete($db,$table,$oursWhere,$ourArgs);
    }
    $phase='independent-zero';
    $verify=$open();
    $remaining=[];
    foreach ($scope as $name=>[$table,$allWhere,$oursWhere,$allArgs,$ourArgs]) {
        $remaining[$name]=$count($verify,'SELECT COUNT(*) FROM '.$table
            .' WHERE '.$allWhere,$allArgs);
    }
    if (array_sum($remaining)!==0) {
        throw new RuntimeException('Exact fixture cleanup incomplete');
    }
    $manifest['permission_fixture_phase']='cleaned';
    $serialized=json_encode($manifest,JSON_UNESCAPED_SLASHES);
    $written=file_put_contents($path,$serialized,LOCK_EX);
    if (!is_int($written) || $written!==strlen($serialized)) {
        throw new RuntimeException('Manifest cleaned-state write failed');
    }
    echo json_encode(['mode'=>'cleanup','marker'=>$marker,
        'before'=>$counts,'after_scope_counts'=>$remaining,
        'all_zero'=>true,'manifest_cleaned'=>true],
        JSON_UNESCAPED_SLASHES).PHP_EOL;
} catch (Throwable $error) {
    echo json_encode(['status'=>'blocked','phase'=>$phase,
        'class'=>get_class($error),
        'code'=>(string)$error->getCode()],JSON_UNESCAPED_SLASHES).PHP_EOL;
    exit(1);
}
