<?php

declare(strict_types=1);

$suite = strtolower((string)($argv[1] ?? ''));

$commonEnv = [
    'USE_ENV' => 'true',
    'CONFIG_DB_TARGET' => 'debug',
    'CONFIG_DB_HOST' => 'mysql-debug',
    'CONFIG_DB_USER' => 'root',
    'CONFIG_DB_PASSWORD' => 'debug_root_password',
    'CONFIG_DB_DATABASE' => 'nnks_db_debug',
    'CONFIG_DB_PORT' => '3306',
    'CONFIG_DB_DEBUG_HOST' => 'mysql-debug',
    'CONFIG_DB_DEBUG_USER' => 'root',
    'CONFIG_DB_DEBUG_PASSWORD' => 'debug_root_password',
    'CONFIG_DB_DEBUG_DATABASE' => 'nnks_db_debug',
    'CONFIG_DB_DEBUG_PORT' => '3306',
    'REDIS_CONFIG_HOST' => 'redis',
    'REDIS_CONFIG_PORT' => '6379',
    'REDIS_CONFIG_DATABASE' => '0',
    'REDIS_CONFIG_DEBUG_HOST' => 'redis',
    'REDIS_CONFIG_DEBUG_PORT' => '6379',
    'REDIS_CONFIG_DEBUG_DATABASE' => '0',
    'EDGE_BROKER_URL' => 'http://edge-broker:4300',
    'EDGE_PUBLIC_BROKER_URL' => '',
    'EDGE_BROKER_SHARED_SECRET' => 'truckwash-edge-ci',
    'EDGE_GATEWAY_VIEW_CACHE_TTL' => '0',
    'TRUCKWASH_TEST_BLOCK_REAL_SHELLY' => '1',
    'MINIO_ENDPOINT' => '',
    'MINIO_ACCESS_KEY' => '',
    'MINIO_SECRET_KEY' => '',
];

foreach ($commonEnv as $key => $value) {
    putenv($key . '=' . $value);
    $_ENV[$key] = $value;
    $_SERVER[$key] = $value;
}

$commands = [
    'unit' => [
        'vendor/bin/pest --testsuite=Unit --colors=always',
    ],
    'integration' => [
        'RUN_INTEGRATION_TESTS=1 vendor/bin/pest --testsuite=Integration --colors=always',
    ],
    'api' => [
        'RUN_API_TESTS=1 API_TEST_FAIL_ON_SKIP=1 API_TEST_BOOTSTRAP_SCHEMA=1 API_TEST_ALLOW_LIVE_DB=1 API_TEST_REQUEST_TIMEOUT=180 vendor/bin/pest --testsuite=Api --colors=always',
    ],
    'legacy' => [
        'RUN_LEGACY_TESTS=1 RUN_INTEGRATION_TESTS=1 RUN_API_TESTS=1 API_TEST_FAIL_ON_SKIP=1 API_TEST_BOOTSTRAP_SCHEMA=1 API_TEST_ALLOW_LIVE_DB=1 API_TEST_REQUEST_TIMEOUT=180 vendor/bin/pest --testsuite=Legacy --colors=always',
    ],
];

/**
 * @param array<int, string> $extensions
 */
function assert_required_php_extensions(array $extensions): void
{
    $missing = array_values(array_filter(
        $extensions,
        static fn (string $extension): bool => !extension_loaded($extension)
    ));

    if ($missing === []) {
        return;
    }

    fwrite(STDERR, 'Missing required PHP extension(s): ' . implode(', ', $missing) . PHP_EOL);
    exit(1);
}

function reset_ci_state(): void
{
    $database = getenv('CONFIG_DB_DATABASE') ?: 'nnks_db_debug';
    if (!preg_match('/^[A-Za-z0-9_]+$/', $database)) {
        fwrite(STDERR, 'Refusing to reset unsafe database name: ' . $database . PHP_EOL);
        exit(2);
    }

    $db = new mysqli(
        getenv('CONFIG_DB_HOST') ?: 'mysql-debug',
        getenv('CONFIG_DB_USER') ?: 'root',
        getenv('CONFIG_DB_PASSWORD') ?: 'debug_root_password',
        '',
        (int)(getenv('CONFIG_DB_PORT') ?: 3306)
    );

    if ($db->connect_errno) {
        fwrite(STDERR, 'Unable to reset CI database: ' . $db->connect_error . PHP_EOL);
        exit(1);
    }

    $db->query("DROP DATABASE IF EXISTS `{$database}`");
    $db->query("CREATE DATABASE `{$database}` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
    $db->close();

    $redisHost = escapeshellarg(getenv('REDIS_CONFIG_HOST') ?: 'redis');
    $redisPort = (int)(getenv('REDIS_CONFIG_PORT') ?: 6379);
    $redisDb = (int)(getenv('REDIS_CONFIG_DATABASE') ?: 0);
    passthru("redis-cli -h {$redisHost} -p {$redisPort} -n {$redisDb} FLUSHDB >/dev/null", $redisExitCode);
    if ($redisExitCode !== 0) {
        fwrite(STDERR, 'Unable to reset CI Redis database.' . PHP_EOL);
        exit($redisExitCode);
    }
}

if ($suite === 'all') {
    foreach (['unit', 'integration', 'api', 'legacy'] as $selectedSuite) {
        if (in_array($selectedSuite, ['api', 'legacy'], true)) {
            assert_required_php_extensions(['mysqli']);
        }

        reset_ci_state();
        foreach ($commands[$selectedSuite] as $command) {
            passthru($command, $exitCode);
            if ($exitCode !== 0) {
                exit($exitCode);
            }
        }
    }
    exit(0);
} elseif (isset($commands[$suite])) {
    $selectedCommands = $commands[$suite];
} else {
    fwrite(STDERR, "Usage: php tests/Support/run_ci_suite.php <unit|integration|api|legacy|all>" . PHP_EOL);
    exit(2);
}

if (in_array($suite, ['api', 'legacy'], true)) {
    assert_required_php_extensions(['mysqli']);
}

foreach ($selectedCommands as $command) {
    passthru($command, $exitCode);
    if ($exitCode !== 0) {
        exit($exitCode);
    }
}
