<?php

namespace App\Http\Controllers;

use App\Http\Middleware\SetLocale;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Str;

class LocaleController extends Controller
{
    public function __invoke(Request $request): RedirectResponse
    {
        $data = $request->validate([
            'locale' => ['required', 'in:'.implode(',', SetLocale::SUPPORTED)],
            'return_to' => ['nullable', 'string', 'max:2048'],
        ]);
        $locale = $data['locale'];
        $request->session()->put('locale', $locale);
        Cookie::queue(cookie('locale', $locale, 60 * 24 * 365, '/', null, $request->isSecure(), true, false, 'lax'));

        if ($request->user()) {
            $request->user()->forceFill(['locale' => $locale])->save();
        }

        $target = $this->safeRelativeTarget($data['return_to'] ?? null)
            ?? $this->safeRefererTarget($request)
            ?? $this->fallbackTarget($request);

        return redirect()->to($target);
    }

    private function safeRelativeTarget(?string $target): ?string
    {
        if (! is_string($target) || ! str_starts_with($target, '/') || str_starts_with($target, '//')) return null;
        $decoded = $target;
        for ($i = 0; $i < 3; $i++) $decoded = rawurldecode($decoded);
        if (! str_starts_with($decoded, '/') || str_starts_with($decoded, '//') || Str::contains($decoded, ["\r", "\n", '\\'])) return null;
        if (parse_url($decoded, PHP_URL_HOST) !== null || parse_url($decoded, PHP_URL_SCHEME) !== null) return null;
        return $target;
    }

    private function safeRefererTarget(Request $request): ?string
    {
        $referer = $request->headers->get('referer');
        if (! $referer) return null;
        $parts = parse_url($referer);
        $requestPort = $request->getPort();
        $refererPort = $parts['port'] ?? (($parts['scheme'] ?? '') === 'https' ? 443 : 80);
        if (($parts['scheme'] ?? null) !== $request->getScheme() || ($parts['host'] ?? null) !== $request->getHost() || $refererPort !== $requestPort) return null;
        return $this->safeRelativeTarget(($parts['path'] ?? '/').(isset($parts['query']) ? '?'.$parts['query'] : ''));
    }

    private function fallbackTarget(Request $request): string
    {
        if ($request->user()?->canAccessPanel(filament()->getPanel('admin'))) return '/admin';
        if ($request->user()) return route('dashboard', absolute: false);
        return route('login', absolute: false);
    }
}
