<?php
declare(strict_types=1);

// Exact recovery for the single B actor whose HTTP completed but cleanup PDO
// disconnected. Never scans or deletes by prefix.
$mode = (string)($argv[1] ?? '');
$journalPath = '/tmp/zhct-user-report-CDXUSR4D32A8929BDB6369A/recovery.json';
$expectedMarker = 'CDXUSR4D32A8929BDB6369A';
$expectedId = 98329;
$expectedDbHash = '003eb5aecf1cd4595b609c1f7f20b9ee325b578309fb9fe14fedaf77584fa401';
if (!in_array($mode, ['--inspect', '--recover'], true)
    || ($mode === '--recover' && ((string)getenv('CDX_USER_RECOVER') !== 'ROOT_EXACT_ACTOR'
        || (string)getenv('CDX_USER_RECOVER_SHA') !== hash_file('sha256', __FILE__)))) {
    fwrite(STDERR, "recovery disabled\n");
    exit(78);
}
if (!is_file($journalPath) || is_link($journalPath)
    || (fileperms($journalPath) & 0777) !== 0600) {
    throw new RuntimeException('Private journal gate failed');
}
$journal = json_decode((string)file_get_contents($journalPath), true);
if (!is_array($journal) || ($journal['lane'] ?? null) !== 'B'
    || ($journal['marker'] ?? null) !== $expectedMarker
    || (int)($journal['operator_id'] ?? 0) !== $expectedId
    || ($journal['database_fingerprint'] ?? null) !== $expectedDbHash
    || ($journal['phase'] ?? null) !== 'needs_recovery'
    || !empty($journal['failure'])) {
    throw new RuntimeException('Journal scope changed');
}
$root = '/tmp/zhct-http-store-mysql.dQTTBP';
$config = require $root . '/application/database.php';
$local = require '/workspace/zhct/zhctproject/store/application/config/local/database.php';
if (!is_array($config) || !is_array($local) || ($config['type'] ?? null) !== 'mysql'
    || ($config['prefix'] ?? null) !== 'ydy_') {
    throw new RuntimeException('Not the reviewed code-local MySQL');
}
foreach (['hostname', 'database', 'username', 'password'] as $key) {
    if (($config[$key] ?? null) !== ($local[$key] ?? null)) {
        throw new RuntimeException('Code-local DB drift');
    }
}
$dsn = 'mysql:host=' . $config['hostname'] . ';port=' . (int)($config['hostport'] ?? 3306)
    . ';dbname=' . $config['database'] . ';charset=' . (string)($config['charset'] ?? 'utf8');
try {
    $pdo = new PDO($dsn, (string)$config['username'], (string)$config['password'],
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_CASE => PDO::CASE_LOWER,
            PDO::ATTR_TIMEOUT => 5]);
    $identity = (string)$pdo->query(
        "SELECT CONCAT(@@server_uuid,'|',@@hostname,'|',@@port,'|',DATABASE())")->fetchColumn();
    if (!hash_equals($expectedDbHash, hash('sha256', $identity))) {
        throw new RuntimeException('DB identity mismatch');
    }
    $stmt = $pdo->prepare('SELECT ID,UUID,ACCOUNT,TYPE,CREATE_BY'
        . ' FROM ydy_user WHERE ID=?');
    $stmt->execute([$expectedId]);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    if ($row && ((int)$row['id'] !== $expectedId
        || $row['uuid'] !== $expectedMarker || $row['account'] !== $expectedMarker
        || (int)$row['type'] !== 0 || $row['create_by'] !== 'CODEX')) {
        throw new RuntimeException('Actor ID belongs to another record');
    }
    $stmt = $pdo->prepare('SELECT COUNT(*) FROM ydy_user WHERE UUID=? OR ACCOUNT=?');
    $stmt->execute([$expectedMarker, $expectedMarker]);
    $markerCount = (int)$stmt->fetchColumn();
    if ($markerCount !== ($row ? 1 : 0)) {
        throw new RuntimeException('Marker collision');
    }
    if ($mode === '--inspect') {
        echo json_encode(['mode' => 'inspect', 'db_identity_match' => true,
            'exact_actor_present' => (bool)$row, 'marker_count' => $markerCount]) . PHP_EOL;
        exit(0);
    }
    if (!$row) {
        throw new RuntimeException('Actor absent; independent verification required');
    }
    $stmt = $pdo->prepare('DELETE FROM ydy_user'
        . ' WHERE ID=? AND UUID=? AND ACCOUNT=? AND TYPE=0 AND CREATE_BY=?');
    $stmt->execute([$expectedId, $expectedMarker, $expectedMarker, 'CODEX']);
    if ($stmt->rowCount() !== 1) {
        throw new RuntimeException('Exact delete count mismatch');
    }
    echo json_encode(['mode' => 'recover', 'db_identity_match' => true,
        'exact_deleted_rows' => 1, 'journal_retained_for_independent_check' => true]) . PHP_EOL;
} catch (Throwable $e) {
    fwrite(STDERR, get_class($e) . ':' . hash('sha256', $e->getMessage()) . "\n");
    exit(1);
}
