<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Models\User;
use App\Services\SystemConfig\SystemConfigService;
use Exception;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Laravel\Socialite\Facades\Socialite;

class SocialAuthController extends Controller
{
    public function __construct(
        protected SystemConfigService $systemConfig
    ) {}

    /**
     * Redirect to Provider OAuth
     */
    public function redirect(string $provider)
    {
        $this->ensureFeatureEnabled($provider);

        // Save provider to session for the unified callback
        session(['social_auth_provider' => $provider]);

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

    /**
     * Handle Provider Callback
     */
    public function callback()
    {
        $provider = session('social_auth_provider');

        if (! $provider) {
            return redirect('/login')->with('error', __('Authentication provider not found in session.'));
        }

        $this->ensureFeatureEnabled($provider);

        try {
            $socialUser = Socialite::driver($provider)->user();
        } catch (Exception $e) {
            return redirect('/login')->with('error', __(':provider authentication failed.', ['provider' => ucfirst($provider)]));
        }

        $idColumn = $provider.'_id'; // google_id, facebook_id, github_id

        // Reject if the OAuth provider signals the email is not verified
        $emailVerified = $socialUser->user['email_verified'] ?? null;
        if ($emailVerified === false) {
            return redirect('/login')->with('error', __('Your :provider email address is not verified. Please verify it and try again.', ['provider' => ucfirst($provider)]));
        }

        // Primary lookup: by provider-specific ID (not spoofable)
        $user = User::where($idColumn, $socialUser->id)->first();

        // Secondary lookup: by email only if no provider-ID match exists yet
        // (covers first-time OAuth login for users who registered via email)
        if (! $user && $socialUser->email) {
            $byEmail = User::where('email', $socialUser->email)->first();
            if ($byEmail) {
                // Only link if the existing account does NOT already belong to a different OAuth identity
                if (empty($byEmail->{$idColumn})) {
                    $user = $byEmail;
                } else {
                    // Email already linked to a different identity on this provider — refuse silently
                    // to avoid leaking that the account exists or letting an attacker take it over.
                    return redirect('/login')->with('error', __('This email is already linked to a different account. Please sign in with your original method.'));
                }
            }
        }

        if (! $user) {
            // Register new user
            $user = User::create([
                'name' => $socialUser->name ?? $socialUser->nickname ?? $socialUser->email,
                'email' => $socialUser->email,
                $idColumn => $socialUser->id,
                'avatar' => $socialUser->avatar,
                'password' => bcrypt(Str::random(32)),
            ]);

            // Assign default role
            $user->assignRole('User');
        } else {
            // Sync Social ID and Avatar
            $user->update([
                $idColumn => $socialUser->id,
                'avatar' => $socialUser->avatar,
            ]);
        }

        Auth::login($user, true);

        session()->forget('social_auth_provider');
        session()->regenerate();

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

    /**
     * Ensure the requested provider is enabled in settings
     */
    protected function ensureFeatureEnabled(string $provider): void
    {
        $settingKey = 'feature_'.$provider.'_oauth';

        if ($provider === 'facebook' || $provider === 'github') {
            // GitHub and Facebook keys follow the 'feature_{provider}_oauth' pattern
        }

        abort_unless($this->systemConfig->get($settingKey, false), 404, __('Provider not enabled.'));
    }
}
