<?php
declare(strict_types=1);

require_once dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'bootstrap.php';

if (!function_exists('quaeriva_api_response')) {
    /**
     * Build the API response without sending it. The public front controller
     * uses this when Apache/LiteSpeed maps /api/v1 through public/index.php.
     *
     * @param array<string, mixed>|null $server
     * @param array<string, mixed>|null $query
     */
    function quaeriva_api_response(?array $server = null, ?array $query = null, ?array $input = null): App\Http\JsonResponse
    {
        $server = $server ?? $_SERVER;
        $query = $query ?? $_GET;
        if ($input === null) {
            $input = $_POST;
            $contentType = strtolower((string) ($server['CONTENT_TYPE'] ?? $server['HTTP_CONTENT_TYPE'] ?? ''));
            if ($input === [] && str_contains($contentType, 'application/json')) {
                $raw = file_get_contents('php://input');
                $decoded = is_string($raw) && trim($raw) !== '' ? json_decode($raw, true) : [];
                $input = is_array($decoded) ? $decoded : [];
            }
        }
        $boot = app_bootstrap();
        $site = $boot['site'];
        $supportedLocales = array_values(array_map('strval', $site['supported_locales'] ?? ['ar', 'en']));
        $pdo = null;
        $settings = null;
        $languageRepository = null;
        $schemaReady = false;

        try {
            $pdo = App\Database\Connection::connect($boot['database']);
            $settings = new App\Settings\SettingsRepository($pdo);
            quaeriva_load_plugins((array) $settings->get('plugins.active', []));
            $schemaReady = (new App\Database\SchemaHealthService($pdo, app_root_path('database', 'migrations')))->isHealthy();
            try {
                $languageRepository = new App\Languages\LanguageRepository($pdo);
                $languageRepository->enabled();
            } catch (Throwable) {
                $languageRepository = null;
            }
            $runtimeDefault = strtolower(str_replace('_', '-', trim((string) $settings->get('site.default_locale', $site['locale'] ?? 'ar'))));
            if (in_array($runtimeDefault, $supportedLocales, true)) {
                $site['locale'] = $runtimeDefault;
            }
        } catch (Throwable) {
            $pdo = null;
            $languageRepository = null;
        }

        $requestedLocale = is_scalar($query['lang'] ?? null) ? strtolower(str_replace('_', '-', trim((string) $query['lang']))) : '';
        $locale = in_array($requestedLocale, $supportedLocales, true) ? $requestedLocale : '';

        if ($locale === '') {
            $acceptLanguage = (string) ($server['HTTP_ACCEPT_LANGUAGE'] ?? '');
            foreach (explode(',', $acceptLanguage) as $part) {
                $candidate = strtolower(str_replace('_', '-', trim((string) preg_replace('/;.*$/', '', $part))));
                $candidates = array_unique([$candidate, explode('-', $candidate)[0]]);
                foreach ($candidates as $candidateLocale) {
                    if (in_array($candidateLocale, $supportedLocales, true)) {
                        $locale = $candidateLocale;
                        break 2;
                    }
                }
            }
        }

        if ($locale === '') {
            $locale = in_array((string) ($site['locale'] ?? ''), $supportedLocales, true)
                ? (string) $site['locale']
                : ($supportedLocales[0] ?? 'ar');
        }

        $basePath = app_base_path((string) ($site['base_url'] ?? ''));
        $configuredOrigin = trim((string) app_env('APP_URL', ''));

        if (!preg_match('~^https?://[A-Za-z0-9.-]+(?::\d{1,5})?$~', $configuredOrigin)) {
            $host = (string) ($server['HTTP_HOST'] ?? '');
            $scheme = !empty($server['HTTPS']) && strtolower((string) $server['HTTPS']) !== 'off' ? 'https' : 'http';
            $configuredOrigin = preg_match('/^[A-Za-z0-9.-]+(?::\d{1,5})?$/', $host) === 1
                ? $scheme . '://' . $host
                : '';
        }

        $canonicalBaseUrl = rtrim($configuredOrigin, '/') . $basePath;
        $apiTranslator = null;
        $fallbackLocale = (string) ($site['locale'] ?? 'ar');
        if ($languageRepository instanceof App\Languages\LanguageRepository) {
            try {
                $fallbackLocale = $languageRepository->fallbackLocaleFor($locale, $fallbackLocale);
                $apiTranslator = new App\Support\Translator(
                    $locale,
                    $fallbackLocale,
                    null,
                    $languageRepository->overrides($locale),
                    $languageRepository->overrides($fallbackLocale),
                );
            } catch (Throwable) {
                $apiTranslator = null;
            }
        }
        if (!$apiTranslator instanceof App\Support\Translator) {
            $apiTranslator = new App\Support\Translator($locale, $fallbackLocale);
        }

        $questionController = $pdo instanceof PDO
            ? new App\Http\QuestionApiController($pdo, $canonicalBaseUrl, new App\Http\QuestionSerializer(), $locale, $apiTranslator, $fallbackLocale)
            : null;

        $mutationController = null;
        $cookieAuthenticated = false;
        if ($schemaReady && $pdo instanceof PDO && $settings instanceof App\Settings\SettingsRepository) {
            $actor = null;
            $scopes = [];
            $authorization = trim((string) ($server['HTTP_AUTHORIZATION'] ?? $server['REDIRECT_HTTP_AUTHORIZATION'] ?? ''));
            if (preg_match('/^Bearer\s+(.+)$/i', $authorization, $matches) === 1) {
                try {
                    $auth = (new App\Auth\ApiTokenService($pdo))->authenticate(trim((string) $matches[1]));
                    if (is_array($auth)) {
                        $actor = $auth['user'];
                        $scopes = $auth['scopes'];
                    }
                } catch (Throwable) {
                    $actor = null;
                    $scopes = [];
                }
            } elseif ($authorization === '') {
                try {
                    App\Web\Session::start();
                    $actor = App\Web\Session::user();
                    if (is_array($actor)) {
                        $cookieAuthenticated = true;
                        $scopes = ['profile:read', 'notifications:read', 'questions:write', 'answers:write', 'comments:write', 'votes:write', 'follows:write', 'answers:accept', 'reports:write'];
                    }
                } catch (Throwable) {
                    $actor = null;
                }
            }
            $mutationController = new App\Http\ApiMutationController($pdo, $actor, $scopes, $settings, $apiTranslator, $canonicalBaseUrl);
        }

        $router = new App\Http\ApiRouter($questionController, $locale, $apiTranslator, $mutationController, $schemaReady, $fallbackLocale);
        $requestPath = (string) ($server['REQUEST_URI'] ?? '/api/v1');
        $requestMethod = (string) ($server['REQUEST_METHOD'] ?? 'GET');

        if ($cookieAuthenticated && in_array(strtoupper($requestMethod), ['POST', 'PUT', 'PATCH', 'DELETE'], true)) {
            $csrfToken = (string) ($server['HTTP_X_CSRF_TOKEN'] ?? $input['_csrf'] ?? '');
            $csrfValid = false;
            if ($csrfToken !== '') {
                try {
                    $csrfValid = (new App\Security\CsrfService())->validate($csrfToken);
                } catch (Throwable) {
                    $csrfValid = false;
                }
            }
            if (!$csrfValid) {
                return App\Http\JsonResponse::failure(403, 'csrf_failed', $apiTranslator->get('api.csrf_failed'));
            }
        }

        return $router->dispatch($requestMethod, $requestPath, $query, $input);
    }
}

if (realpath((string) ($_SERVER['SCRIPT_FILENAME'] ?? '')) === realpath(__FILE__)) {
    quaeriva_api_response()->send();
}
