<?php

declare(strict_types=1);

// Route registration is read-only. No application request or database connection is started.
$root = rtrim((string)getenv('POC_STORE_SOURCE_ROOT'), '/');
if ($root === '' || !is_file($root . '/application/route.php')) {
    throw new RuntimeException('Store source root required');
}
define('TP_ENV', (string)(getenv('POC_ROUTE_ENV') ?: 'dev'));
define('BUSINESS', (string)(getenv('POC_ROUTE_BUSINESS') ?: 'zhct_dev'));
chdir($root);
require $root . '/thinkphp/base.php';
require $root . '/application/route.php';

$routes = [];
foreach (\think\Route::rules() as $bucket => $entries) {
    foreach ($entries as $prefix => $entry) {
        if (!is_array($entry)) continue;
        if (isset($entry['rule']) && is_array($entry['rule'])) {
            foreach ($entry['rule'] as $child) {
                if (!is_array($child) || !isset($child['rule'])) continue;
                $method = strtoupper((string)($child['option']['method'] ?? $bucket));
                $path = '/' . trim((string)$prefix . '/' . (string)$child['rule'], '/');
                $key = $method . ' ' . $path;
                $target = (string)($child['route'] ?? '');
                $controllerPrefix = (string)($child['option']['prefix'] ?? '');
                $routes[$key] = [
                    'method' => $method,
                    'path' => $path,
                    'target' => $target,
                    'resolved_target' => strpos($target, '/') === 0 && $controllerPrefix !== ''
                        ? rtrim($controllerPrefix, '/') . $target : $target,
                    'bucket' => $bucket,
                ];
            }
        } elseif (isset($entry['route']) && $bucket !== '*') {
            $method = strtoupper((string)$bucket);
            $path = '/' . trim((string)$prefix, '/');
            $routes[$method . ' ' . $path] = [
                'method' => $method, 'path' => $path,
                'target' => (string)$entry['route'],
                'resolved_target' => (string)$entry['route'], 'bucket' => $bucket,
            ];
        }
    }
}
ksort($routes);
$matrixPath = (string)getenv('POC_MATRIX_PATH');
if ($matrixPath !== '') {
    $file = fopen($matrixPath, 'rb');
    if (!$file) throw new RuntimeException('Cannot read interface matrix');
    $headings = fgetcsv($file);
    $indexes = array_flip($headings);
    $known = [];
    $knownAny = [];
    $knownPath = [];
    while (($row = fgetcsv($file)) !== false) {
        $identity = ($row[$indexes['method']] ?? '') . ' ' . ($row[$indexes['path']] ?? '');
        $knownAny[$identity] = true;
        $knownPath[$row[$indexes['path']] ?? ''] = true;
        if (($row[$indexes['repo']] ?? '') !== 'store') continue;
        $known[$identity] = true;
    }
    fclose($file);
    $missing = array_values(array_filter($routes, static function ($route) use ($known) {
        return !isset($known[$route['method'] . ' ' . $route['path']]);
    }));
    $missingExact = array_values(array_filter($routes, static function ($route) use ($knownAny) {
        return !isset($knownAny[$route['method'] . ' ' . $route['path']]);
    }));
    $missingPath = array_values(array_filter($routes, static function ($route) use ($knownPath) {
        return !isset($knownPath[$route['path']]);
    }));
    echo json_encode(['environment' => TP_ENV, 'business' => BUSINESS,
        'registered_count' => count($routes), 'matrix_store_count' => count($known),
        'unlisted_registered_count' => count($missing),
        'missing_exact_method_path' => count($missingExact),
        'missing_even_by_path' => count($missingPath),
        'unlisted_first_20' => array_slice($missing, 0, 20)],
        JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
    exit;
}
echo json_encode(['environment' => TP_ENV, 'business' => BUSINESS,
    'routes' => array_values($routes)], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
