<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Laravel\Socialite\Facades\Socialite;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Throwable;

class TenantAdminGoogleController extends Controller
{
    public function redirect(Request $request): RedirectResponse
    {
        $returnTo = $request->query('return_to');
        if (is_string($returnTo) && $returnTo !== '') {
            $request->session()->put('tenant_oauth_return_to', $returnTo);
        }

        return Socialite::driver('google')
            ->scopes(['openid', 'profile', 'email'])
            ->with(['prompt' => 'select_account'])
            ->redirect();
    }

    public function callback(Request $request)
    {
        try {
            $googleUser = Socialite::driver('google')->user();
        } catch (Throwable $exception) {
            Log::warning('Tenant admin Google sign-in failed', [
                'message' => $exception->getMessage(),
            ]);

            return $this->sendBackWithError($request, 'google_failed', 'Unable to complete Google sign-in.');
        }

        $email = $googleUser->getEmail();
        if (! $email) {
            return $this->sendBackWithError($request, 'google_failed', 'Google account did not provide an email address.');
        }

        /** @var User|null $user */
        $user = User::query()->where('email', $email)->first();

        if (! $user || ! in_array($user->role, ['tenant_admin', 'super_admin', 'superadmin'], true)) {
            return $this->sendBackWithError($request, 'google_no_match', 'No tenant admin account is linked to this Google address.');
        }

        $user->forceFill([
            'name' => $googleUser->getName() ?: $user->name,
            'email_verified_at' => $user->email_verified_at ?? now(),
        ])->save();

        Auth::login($user, true);
        $request->session()->regenerate();

        $returnTo = $request->session()->pull('tenant_oauth_return_to');
        if (is_string($returnTo)) {
            $decoded = $this->decodeReturnTo($returnTo, $request);
            if ($decoded) {
                return redirect()->to($decoded);
            }
        }

        return redirect()->intended('/event-admin/dashboard');
    }

    private function sendBackWithError(Request $request, string $code, string $message): RedirectResponse
    {
        $query = [
            'error' => $code,
            'error_description' => $message,
        ];

        if ($request->session()->has('tenant_oauth_return_to')) {
            $query['return_to'] = $request->session()->get('tenant_oauth_return_to');
        }

        return redirect()->route('tenant.admin.login', $query);
    }

    private function decodeReturnTo(string $encoded, Request $request): ?string
    {
        $padded = str_pad($encoded, strlen($encoded) + ((4 - (strlen($encoded) % 4)) % 4), '=');
        $normalized = strtr($padded, '-_', '+/');
        $decoded = base64_decode($normalized);

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

        $targetHost = parse_url($decoded, PHP_URL_HOST);
        $appHost = parse_url($request->getSchemeAndHttpHost(), PHP_URL_HOST);

        if ($targetHost && $appHost && ! Str::endsWith($targetHost, $appHost)) {
            return null;
        }

        return $decoded;
    }
}
