<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\SocialAccount;
use App\Services\RegistrationService;
use App\Services\RoleAssignmentService;
use Laravel\Socialite\Facades\Socialite;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Exception;

class SocialAuthController extends Controller
{
    protected RegistrationService $registrationService;
    protected RoleAssignmentService $roleService;

    public function __construct(RegistrationService $registrationService, RoleAssignmentService $roleService)
    {
        $this->registrationService = $registrationService;
        $this->roleService = $roleService;
    }

    /**
     * Redirect to the provider's OAuth page.
     */
    public function redirectToProvider(string $provider): RedirectResponse
    {
        $validProviders = ['google', 'facebook', 'github'];

        if (!in_array($provider, $validProviders)) {
            return redirect()->route('login')
                ->withErrors(['social' => 'Invalid login provider.']);
        }

        return Socialite::driver($provider)->redirect();
    }

    /**
     * Handle the OAuth callback from the provider.
     */
    public function handleProviderCallback(string $provider): RedirectResponse
    {
        $validProviders = ['google', 'facebook', 'github'];

        if (!in_array($provider, $validProviders)) {
            return redirect()->route('login')
                ->withErrors(['social' => 'Invalid login provider.']);
        }

        try {
            $socialUser = Socialite::driver($provider)->user();
        } catch (Exception $e) {
            return redirect()->route('login')
                ->withErrors(['social' => 'Unable to login with ' . ucfirst($provider) . '. Please try again.']);
        }

        // Check if email is provided
        if (!$socialUser->getEmail()) {
            return redirect()->route('login')
                ->withErrors(['social' => 'Email address is required. Please add an email to your ' . ucfirst($provider) . ' account.']);
        }

        // Check if social account already exists
        $socialAccount = SocialAccount::findByProvider($provider, $socialUser->getId());

        if ($socialAccount) {
            // Existing account - log the user in
            $user = $socialAccount->user;

            if (!$user->is_active) {
                return redirect()->route('login')
                    ->withErrors(['social' => 'Your account has been deactivated.']);
            }

            // Update social account tokens
            $socialAccount->update([
                'provider_token' => $socialUser->token,
                'provider_refresh_token' => $socialUser->refreshToken,
                'provider_name' => $socialUser->getName(),
                'provider_avatar' => $socialUser->getAvatar(),
            ]);

            Auth::login($user, true);

            return redirect()->intended($user->getDashboardUrl());
        }

        // Check if user with this email already exists
        $user = User::where('email', $socialUser->getEmail())->first();

        if ($user) {
            // Check active status before linking
            if (!$user->is_active) {
                return redirect()->route('login')
                    ->withErrors(['social' => 'Your account has been deactivated.']);
            }

            // Link social account to existing user
            SocialAccount::create([
                'user_id'                => $user->id,
                'provider'               => $provider,
                'provider_id'            => $socialUser->getId(),
                'provider_token'         => $socialUser->token,
                'provider_refresh_token' => $socialUser->refreshToken,
                'provider_email'         => $socialUser->getEmail(),
                'provider_name'          => $socialUser->getName(),
                'provider_avatar'        => $socialUser->getAvatar(),
            ]);

            Auth::login($user, true);

            return redirect()->intended($user->getDashboardUrl());
        }

        // New user - need to select role first
        session([
            'social_auth' => [
                'provider' => $provider,
                'provider_id' => $socialUser->getId(),
                'token' => $socialUser->token,
                'refresh_token' => $socialUser->refreshToken,
                'name' => $socialUser->getName(),
                'email' => $socialUser->getEmail(),
                'avatar' => $socialUser->getAvatar(),
                'nickname' => $socialUser->getNickname(),
            ],
        ]);

        return redirect()->route('auth.social.role-select');
    }

    /**
     * Show role selection form for new social users.
     */
    public function showRoleSelectForm()
    {
        if (!session('social_auth')) {
            return redirect()->route('login');
        }

        $roles = $this->registrationService->getAvailableRoles();

        return view('auth.social-role-select', compact('roles'));
    }

    /**
     * Complete social registration with selected role.
     */
    public function completeRegistration(Request $request): RedirectResponse
    {
        $request->validate([
            'role' => ['required', 'string', 'exists:roles,name', 'not_in:Super Manager,Manager'],
        ]);

        $socialData = session('social_auth');

        if (!$socialData) {
            return redirect()->route('login')
                ->withErrors(['social' => 'Session expired. Please try again.']);
        }

        // Create user (or retrieve if already exists due to race condition)
        $user = $this->registrationService->createFromSocial($socialData, $socialData['provider']);

        // Assign selected role (only if user doesn't already have a role)
        if ($user->roles->isEmpty()) {
            $this->roleService->assignRole($user, $request->role);
        }

        // Create social account record only if it doesn't already exist
        $existingSocialAccount = SocialAccount::where('provider', $socialData['provider'])
            ->where('provider_id', $socialData['provider_id'])
            ->first();

        if (!$existingSocialAccount) {
            SocialAccount::create([
                'user_id'                => $user->id,
                'provider'               => $socialData['provider'],
                'provider_id'            => $socialData['provider_id'],
                'provider_token'         => $socialData['token'],
                'provider_refresh_token' => $socialData['refresh_token'],
                'provider_email'         => $socialData['email'],
                'provider_name'          => $socialData['name'],
                'provider_avatar'        => $socialData['avatar'],
            ]);
        }

        // Clear session
        session()->forget('social_auth');

        // Log in the user
        Auth::login($user, true);

        return redirect()->to($user->getDashboardUrl())
            ->with('status', 'Welcome! Your account has been created successfully.');
    }

    /**
     * Unlink a social account from user.
     */
    public function unlink(Request $request, string $provider): RedirectResponse
    {
        $user = $request->user();

        $socialAccount = $user->socialAccounts()->where('provider', $provider)->first();

        if (!$socialAccount) {
            return back()->withErrors(['social' => 'Social account not found.']);
        }

        // Don't allow unlinking if user has no password
        if (!$user->password) {
            return back()->withErrors(['social' => 'Please set a password before unlinking this account.']);
        }

        $socialAccount->delete();

        return back()->with('status', ucfirst($provider) . ' account unlinked successfully.');
    }
}
