<?php

namespace App\Http\Middleware;

use App\Services\PreferencesStore;
use App\Support\LocaleOptions;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

class SetLocale
{
    public function handle(Request $request, Closure $next): Response
    {
        $available = LocaleOptions::available();
        $fallback = LocaleOptions::normalizeOrFallback((string) config('app.fallback_locale', 'en'));

        $sessionLang = $request->session()->get('budgets.language');
        if (is_string($sessionLang) && LocaleOptions::isAvailable($sessionLang)) {
            app()->setLocale($sessionLang);

            return $next($request);
        }

        if (Auth::check()) {
            $prefs = PreferencesStore::all();
            $prefLang = $prefs['regional']['language'] ?? null;
            if (is_string($prefLang) && LocaleOptions::isAvailable($prefLang)) {
                app()->setLocale($prefLang);

                return $next($request);
            }
        }

        app()->setLocale($this->detectFromBrowser($request, $available, $fallback));

        return $next($request);
    }

    /**
     * @param  list<string>  $available
     */
    private function detectFromBrowser(Request $request, array $available, string $fallback): string
    {
        $map = config('localization.from_browser_primary', []);
        if (! is_array($map)) {
            $map = [];
        }

        foreach ($request->getLanguages() as $tag) {
            $normalized = strtolower(str_replace('_', '-', (string) $tag));
            $primary = strstr($normalized, '-', true) ?: $normalized;

            if ($primary !== '' && isset($map[$primary]) && is_string($map[$primary])) {
                $candidate = $map[$primary];
                if (LocaleOptions::isAvailable($candidate)) {
                    return $candidate;
                }
            }

            if ($primary !== '' && LocaleOptions::isAvailable($primary)) {
                return $primary;
            }
        }

        return LocaleOptions::isAvailable($fallback) ? $fallback : $available[0];
    }
}
