<?php
declare(strict_types=1);

// This file never sends a business request or writes to a database.
// Default invocation is denied. The optional read-only phase checks only
// process identity, in-memory configuration parity, source presence, and
// the isolated HTTP boundary endpoint.
$stage = 'default_deny';
set_exception_handler(static function (Throwable $error) use (&$stage): void {
    echo json_encode([
        'status' => 'redacted_error',
        'stage' => $stage,
        'error_class' => get_class($error),
    ], JSON_UNESCAPED_SLASHES), PHP_EOL;
    exit(2);
});
set_error_handler(static function (int $severity): bool {
    if (!(error_reporting() & $severity)) {
        return false;
    }
    throw new ErrorException('redacted warning', 0, $severity);
});

$target = (string)getenv('CDX_READ4_TARGET');
if (getenv('CDX_READ4_PREFLIGHT') !== '1') {
    echo json_encode([
        'status' => 'default_deny',
        'target' => in_array($target, ['A', 'B', 'C'], true) ? $target : 'unset',
        'business_http_sent' => false,
        'database_connected' => false,
        'dml_sent' => false,
    ], JSON_UNESCAPED_SLASHES), PHP_EOL;
    exit(78);
}

$targets = [
    'A' => ['/private/tmp/zhct-http-ai-macos.zjaU8h', 18105],
    'B' => ['/private/tmp/zhct-http-ai-macos.x2CCZX', 18101],
    'C' => ['/tmp/zhct-ai-http-20260929.3XDj3w', 18102],
];
if (!isset($targets[$target])) {
    throw new RuntimeException('Explicit target required');
}
[$root, $port] = $targets[$target];
$stage = 'isolated_process';
if ($target === 'C') {
    $pid = 53772;
    $cmdline = file_get_contents('/proc/' . $pid . '/cmdline');
    $rawEnvironment = file_get_contents('/proc/' . $pid . '/environ');
    if (!is_string($cmdline) || !is_string($rawEnvironment)
        || strpos($cmdline, '127.0.0.1:' . $port) === false
        || strpos($cmdline, $root . '/public') === false) {
        throw new RuntimeException('C process identity mismatch');
    }
    $environment = [];
    foreach (explode("\0", $rawEnvironment) as $part) {
        if (strpos($part, 'POC_') !== 0) {
            continue;
        }
        $separator = strpos($part, '=');
        if ($separator !== false) {
            $environment[substr($part, 0, $separator)] = substr($part, $separator + 1);
        }
    }
    $required = [
        'POC_DIALECT' => 'dm',
        'POC_EXTERNAL_STUBS' => '1',
        'POC_AI_HOST' => '127.0.0.1',
        'POC_AI_PORT' => '5238',
        'POC_AI_SCHEMA' => 'AIZHCT_APP',
        'POC_HOST' => '127.0.0.1',
        'POC_PORT' => '5237',
        'POC_SCHEMA' => 'ZHCT_APP',
    ];
    foreach ($required as $key => $value) {
        if (($environment[$key] ?? null) !== $value) {
            throw new RuntimeException('C POC database boundary mismatch');
        }
    }
} else {
    $pidText = shell_exec('/usr/sbin/lsof -t -nP -iTCP:' . $port
        . ' -sTCP:LISTEN 2>/dev/null');
    $pids = array_values(array_filter(explode("\n", trim((string)$pidText)),
        static function (string $item): bool { return ctype_digit($item); }));
    if (count($pids) !== 1) {
        throw new RuntimeException('A/B single listener required');
    }
    $cmdline = shell_exec('/bin/ps eww -p ' . $pids[0] . ' -o command=');
    $displayRoot = str_replace('/private/tmp/', '/tmp/', $root);
    if (!is_string($cmdline) || strpos($cmdline, '-S 127.0.0.1:' . $port) === false
        || (strpos($cmdline, $root . '/public') === false
            && strpos($cmdline, $displayRoot . '/public') === false)) {
        throw new RuntimeException('A/B isolated PHP runtime mismatch');
    }
    $local = realpath('/Users/wiscourper/Documents/workspace/zhct/zhctproject/ai_api/.env.local');
    if ($local !== '/Users/wiscourper/Documents/workspace/zhct/zhctproject/ai_api/.env.local') {
        throw new RuntimeException('Approved local development config required');
    }
    $ini = parse_ini_file($local, true, INI_SCANNER_RAW);
    if (!is_array($ini) || !isset($ini['DATABASE'], $ini['DATABASE_ZHCT'])) {
        throw new RuntimeException('Local development database config unavailable');
    }
    foreach (['DATABASE' => 'POC_AI_', 'DATABASE_ZHCT' => 'POC_'] as $section => $prefix) {
        foreach (['HOSTNAME' => 'HOST', 'HOSTPORT' => 'PORT', 'DATABASE' => 'SCHEMA',
            'USERNAME' => 'USER', 'PASSWORD' => 'PASSWORD'] as $field => $suffix) {
            $assignment = $prefix . $suffix . '=' . (string)($ini[$section][$field] ?? '');
            if ($assignment === $prefix . $suffix . '='
                || preg_match('/(?:^|\s)' . preg_quote($assignment, '/') . '(?=\s|$)/',
                    $cmdline) !== 1) {
                throw new RuntimeException('A/B runtime differs from .env.local');
            }
        }
    }
}

$stage = 'external_stub_boundary';
$boundaryRaw = file_get_contents('http://127.0.0.1:' . $port . '/__poc_boundary');
$boundary = json_decode((string)$boundaryRaw, true);
if (!is_array($boundary) || ($boundary['external_stubs'] ?? null) !== true) {
    throw new RuntimeException('External stub boundary unavailable');
}

$stage = 'source_presence';
$files = [
    'controller_user' => 'app/api/controller/User.php',
    'controller_archive' => 'app/api/controller/health/Archive.php',
    'controller_restaurant' => 'app/api/controller/Restaurant.php',
    'account_balance' => 'app/common/service/account/AccountSettlementService.php',
    'meal_read_service' => 'app/api/service/meal/Meal.php',
];
$sourceSha = [];
foreach ($files as $label => $relative) {
    $path = $root . '/' . $relative;
    if (!is_file($path) || !is_readable($path)) {
        throw new RuntimeException('Approved runtime source missing');
    }
    $sourceSha[$label] = hash_file('sha256', $path);
}

echo json_encode([
    'status' => 'read_only_boundary_pass',
    'target' => $target,
    'route_whitelist_count' => 4,
    'runtime_process_match' => true,
    'configured_database_boundary_match' => true,
    'external_stubs' => true,
    'source_sha256' => $sourceSha,
    'database_connected' => false,
    'business_http_sent' => false,
    'dml_sent' => false,
], JSON_UNESCAPED_SLASHES), PHP_EOL;
