<?php

declare(strict_types=1);

namespace App\Http\Middleware;

use App\Models\User;
use App\Support\UsernamePolicy;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Symfony\Component\HttpFoundation\Response;

class RedirectLegacyProfileSubdomain
{
    public function handle(Request $request, Closure $next): Response
    {
        $canonicalUsername = $this->resolveCanonicalUsername($request);

        if ($canonicalUsername !== null) {
            return redirect()->to($this->targetUrl($request, $canonicalUsername), 301);
        }

        return $next($request);
    }

    private function resolveCanonicalUsername(Request $request): ?string
    {
        $configuredHost = parse_url((string) config('app.url'), PHP_URL_HOST);

        if (! is_string($configuredHost) || $configuredHost === '') {
            return null;
        }

        $requestHost = strtolower($request->getHost());
        $configuredHost = strtolower($configuredHost);

        if ($requestHost === $configuredHost || ! str_ends_with($requestHost, '.' . $configuredHost)) {
            return null;
        }

        $subdomain = substr($requestHost, 0, -strlen('.' . $configuredHost));

        if ($subdomain === '' || str_contains($subdomain, '.')) {
            return null;
        }

        $candidate = UsernamePolicy::normalize($subdomain);

        if ($candidate === '' || $this->isReservedSubdomain($candidate)) {
            return null;
        }

        $username = User::query()
            ->whereRaw('LOWER(username) = ?', [$candidate])
            ->value('username');

        if (is_string($username) && $username !== '') {
            return UsernamePolicy::normalize($username);
        }

        if (! Schema::hasTable('username_redirects')) {
            return null;
        }

        $redirect = DB::table('username_redirects')
            ->whereRaw('LOWER(old_username) = ?', [$candidate])
            ->value('new_username');

        return is_string($redirect) && $redirect !== ''
            ? UsernamePolicy::normalize($redirect)
            : null;
    }

    private function isReservedSubdomain(string $candidate): bool
    {
        $reserved = UsernamePolicy::reserved();

        foreach ([config('cp.webroot'), config('cpad.webroot')] as $prefix) {
            $value = strtolower(trim((string) $prefix, '/'));
            if ($value !== '') {
                $reserved[] = $value;
            }
        }

        return in_array($candidate, array_values(array_unique($reserved)), true);
    }

    private function targetUrl(Request $request, string $username): string
    {
        $canonicalPath = match ($request->getPathInfo()) {
            '/gallery', '/gallery/' => '/@' . $username . '/gallery',
            default => '/@' . $username,
        };

        $target = rtrim((string) config('app.url'), '/') . $canonicalPath;
        $query = $request->getQueryString();

        if (is_string($query) && $query !== '') {
            $target .= '?' . $query;
        }

        return $target;
    }
}
