<?php

if (!defined('WD')) {
    define('WD', dirname(__DIR__, 2));
}

function app_path(string $relative = ''): string
{
    if ($relative === '') {
        return WD;
    }

    $normalized = ltrim(str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $relative), DIRECTORY_SEPARATOR);

    if (str_starts_with($normalized, 'classes' . DIRECTORY_SEPARATOR . 'edge_gateway_')) {
        $normalized = 'modules' . DIRECTORY_SEPARATOR . 'edgegateway' . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . basename($normalized);
    } elseif ($normalized === 'routes' . DIRECTORY_SEPARATOR . 'edgeGatewaysRoute.php') {
        $normalized = 'modules' . DIRECTORY_SEPARATOR . 'edgegateway' . DIRECTORY_SEPARATOR . 'routes' . DIRECTORY_SEPARATOR . 'edgeGatewaysRoute.php';
    } elseif ($normalized === 'routes' . DIRECTORY_SEPARATOR . 'moduleEdgeGatewayRoute.php') {
        $normalized = 'modules' . DIRECTORY_SEPARATOR . 'edgegateway' . DIRECTORY_SEPARATOR . 'routes' . DIRECTORY_SEPARATOR . 'moduleEdgeGatewayRoute.php';
    } elseif ($normalized === 'routes' . DIRECTORY_SEPARATOR . 'edgeGatewayConfigRoute.php') {
        $normalized = 'modules' . DIRECTORY_SEPARATOR . 'edgegateway' . DIRECTORY_SEPARATOR . 'routes' . DIRECTORY_SEPARATOR . 'edgeGatewayConfigRoute.php';
    }

    return WD . DIRECTORY_SEPARATOR . $normalized;
}

function app_require(string $relative): void
{
    require_once app_path($relative);
}

spl_autoload_register(function (string $class): void {
    $class = ltrim($class, '\\');
    if ($class === '') {
        return;
    }

    $parts = explode('\\', $class);
    $top = strtolower($parts[0] ?? '');
    $relative = implode(DIRECTORY_SEPARATOR, array_slice($parts, 1));

    if ($relative === '') {
        return;
    }

    $base = app_path();
    $candidates = [];

    if (in_array($top, ['classes', 'interfaces', 'traits', 'objects', 'routes', 'statistics'], true)) {
        if ($top === 'classes' && str_starts_with(strtolower($relative), 'edge_gateway_')) {
            $candidates[] = $base . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'edgegateway' . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . $relative;
        }
        if ($top === 'routes' && in_array($relative, ['edgeGatewaysRoute', 'moduleEdgeGatewayRoute', 'edgeGatewayConfigRoute'], true)) {
            $candidates[] = $base . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'edgegateway' . DIRECTORY_SEPARATOR . 'routes' . DIRECTORY_SEPARATOR . $relative;
        }
        $candidates[] = $base . DIRECTORY_SEPARATOR . $top . DIRECTORY_SEPARATOR . $relative;
    } elseif ($top === 'modules') {
        $candidates[] = $base . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . $relative;
    } else {
        $candidates[] = $base . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $class);
        $modules_root = $base . DIRECTORY_SEPARATOR . 'modules';
        if (is_dir($modules_root)) {
            $module_dirs = array_filter(scandir($modules_root) ?: [], static function (string $entry) use ($modules_root): bool {
                return $entry !== '.' && $entry !== '..' && is_dir($modules_root . DIRECTORY_SEPARATOR . $entry);
            });
            foreach ($module_dirs as $module_dir) {
                $candidates[] = $modules_root . DIRECTORY_SEPARATOR . $module_dir . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $class);
            }
        }
    }

    foreach ($candidates as $path) {
        foreach (['', '_t', '_o', '_s', '_i', '_c', '_m'] as $suffix) {
            $file = $path . $suffix . '.php';
            if (!is_file($file)) {
                continue;
            }

            require_once $file;
            if (
                class_exists($class, false)
                || interface_exists($class, false)
                || trait_exists($class, false)
                || (function_exists('enum_exists') && enum_exists($class, false))
            ) {
                return;
            }
        }
    }
});

function integration_enabled(): bool
{
    return getenv('RUN_INTEGRATION_TESTS') === '1';
}

$edgeBrokerSharedSecret = trim((string)(getenv('EDGE_BROKER_SHARED_SECRET') ?: ''));
if ($edgeBrokerSharedSecret === '') {
    $edgeBrokerSharedSecret = 'truckwash-edge-test-secret';
    putenv('EDGE_BROKER_SHARED_SECRET=' . $edgeBrokerSharedSecret);
    $_ENV['EDGE_BROKER_SHARED_SECRET'] = $edgeBrokerSharedSecret;
    $_SERVER['EDGE_BROKER_SHARED_SECRET'] = $edgeBrokerSharedSecret;
}

$shellyGuardEnabled = trim((string)(getenv('TRUCKWASH_TEST_BLOCK_REAL_SHELLY') ?: ''));
if ($shellyGuardEnabled === '') {
    putenv('TRUCKWASH_TEST_BLOCK_REAL_SHELLY=1');
    $_ENV['TRUCKWASH_TEST_BLOCK_REAL_SHELLY'] = '1';
    $_SERVER['TRUCKWASH_TEST_BLOCK_REAL_SHELLY'] = '1';
}

$shellyGuardLogPath = trim((string)(getenv('TRUCKWASH_TEST_SHELLY_GUARD_LOG') ?: ''));
if ($shellyGuardLogPath === '') {
    $shellyGuardLogPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'truckwash-shelly-guard-' . getmypid() . '.jsonl';
    @unlink($shellyGuardLogPath);
    putenv('TRUCKWASH_TEST_SHELLY_GUARD_LOG=' . $shellyGuardLogPath);
    $_ENV['TRUCKWASH_TEST_SHELLY_GUARD_LOG'] = $shellyGuardLogPath;
    $_SERVER['TRUCKWASH_TEST_SHELLY_GUARD_LOG'] = $shellyGuardLogPath;
}

function shelly_test_guard_log_path(): ?string
{
    $path = trim((string)(getenv('TRUCKWASH_TEST_SHELLY_GUARD_LOG') ?: ''));
    return $path === '' ? null : $path;
}

function shelly_test_guard_reset(): void
{
    if (class_exists(\classes\shelly::class, false)) {
        \classes\shelly::resetBlockedRequestLog();
    }

    $path = shelly_test_guard_log_path();
    if ($path !== null && is_file($path)) {
        @unlink($path);
    }
}

/**
 * @return array<int,array<string,mixed>>
 */
function shelly_test_guard_entries(): array
{
    $entries = [];

    if (class_exists(\classes\shelly::class, false)) {
        $entries = array_merge($entries, \classes\shelly::blockedRequestLog());
    }

    $path = shelly_test_guard_log_path();
    if ($path === null || !is_file($path)) {
        return $entries;
    }

    $lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    if ($lines === false) {
        return $entries;
    }

    foreach ($lines as $line) {
        $decoded = json_decode($line, true);
        if (is_array($decoded)) {
            $entries[] = $decoded;
        }
    }

    return $entries;
}

function run_legacy_script(string $relativeScriptPath): array
{
    $script = app_path($relativeScriptPath);
    if (!is_file($script)) {
        return ['exitCode' => 1, 'output' => 'Missing legacy script: ' . $script];
    }

    $phpBinary = PHP_BINARY ?: 'php';
    $command = escapeshellarg($phpBinary) . ' ' . escapeshellarg($script) . ' 2>&1';
    $outputLines = [];
    $exitCode = 0;
    exec($command, $outputLines, $exitCode);

    return ['exitCode' => $exitCode, 'output' => implode(PHP_EOL, $outputLines)];
}

require_once __DIR__ . '/ApiTestSupport.php';
if (class_exists(\PHPUnit\Framework\TestCase::class)) {
    require_once __DIR__ . '/Api/ApiTestCase.php';
}
