<?php

declare(strict_types=1);

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Applies the caller's locale for the duration of the request.
 *
 * Prices, dates and validation messages are all rendered server-side, so
 * without this every response is formatted for one hardcoded locale regardless
 * of what the account asked for -- a user whose profile says `ne` still saw US
 * number formatting on every figure.
 *
 * Precedence is deliberate: an authenticated user's stored preference wins over
 * the browser's Accept-Language, because it is an explicit choice rather than an
 * inference. Only locales the application actually ships are honoured; an
 * arbitrary header value must never reach the translator or ICU.
 */
final class SetLocale
{
    /** @var list<string> */
    private const SUPPORTED = ['en', 'ne'];

    public function handle(Request $request, Closure $next): Response
    {
        $locale = $this->fromUser($request) ?? $this->fromHeader($request);

        if ($locale !== null) {
            app()->setLocale($locale);
        }

        return $next($request);
    }

    private function fromUser(Request $request): ?string
    {
        $locale = $request->user()?->locale;

        return $this->supported(is_string($locale) ? $locale : null);
    }

    private function fromHeader(Request $request): ?string
    {
        $preferred = $request->getPreferredLanguage(self::SUPPORTED);

        return $this->supported(is_string($preferred) ? $preferred : null);
    }

    private function supported(?string $locale): ?string
    {
        if ($locale === null) {
            return null;
        }

        // Match on the language subtag, so "en-GB" resolves to "en".
        $language = strtolower(explode('_', str_replace('-', '_', $locale))[0]);

        return in_array($language, self::SUPPORTED, true) ? $language : null;
    }
}
