<?php

namespace App\Http\Controllers\Auth;

//Library
use App\Http\Controllers\Controller;
use App\Services\JwtService;
use App\Services\UserPrivilegeService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Laravel\Socialite\Facades\Socialite;
use Throwable;
use Illuminate\Support\Facades\Log;
use GuzzleHttp\Exception\ClientException;

//Models
use App\Models\Auth\User;
use App\Models\Auth\UserRole;
use App\Models\Auth\UserPermission;
use App\Models\Esi\EsiScope;
use App\Models\Esi\EsiToken;

class EveLoginController extends Controller
{
    public function showLogin()
    {
        return view('auth.eve');
    }

    public function logout(Request $request) {
        auth()->logout();
        request()->session()->invalidate();
        request()->session()->regenerateToken();
        return redirect('/')->with('success', 'You have been logged out.');
    }

    public function redirectToProvider(): RedirectResponse
    {
        // "eveonline" driver registered via SocialiteProviders
        return Socialite::driver('eveonline')->scopes(['publicData'])->redirect();
    }

    public function handleProviderCallback(Request $request, JwtService $jwtService): RedirectResponse
    {
        try {
            $ssoUser = Socialite::driver('eveonline')->user();

            $user = $this->CreateOrUpdateUser($ssoUser);

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

            // Always regenerate JWT on successful login
            $jwtService->forceRefresh($user);

            //Regenerate the session
            $request->session()->regenerate();
            //Send the user to the dashboard
            return redirect()->route('dashboard');
        } catch (ClientException $e) {
            Log::error('EVE SSO Client Exception', [
                'message' => $e->getMessage(),
                'exception' => get_class($e),
            ]);

            return redirect()
                ->route('login.eve')
                ->with('error', 'EVE token exchange failed. Check client ID, client secret, and redirect URI.');
        } catch (Throwable $e) {
            Log::error('EVE SSO callback failed', [
                'message' => $e->getMessage(),
                'exception' => get_class($e),
            ]);

            report($e);

            return redirect()
                ->route('login.eve')
                ->with('error', 'SSO login failed. Please try again.' . $e);
        }
    }

    private function CreateOrUpdateUser($ssoUser)
    {
        $user = new User;
        $privilege = new UserPrivilegeService;

        //Get all the data we need from the ssoUser
        $characterId = strtr($ssoUser['sub'], ['CHARACTER:EVE:' => '']);
        $characterName = $ssoUser['name'];
        $characterOwnerHash = $ssoUser['owner'];
        $avatar = 'https://image.eveonline.com/Character/' . $characterId . '_128.jpg';
        $token = $ssoUser->token;
        $refreshToken = $ssoUser->refreshToken ?? null;
        $expiresIn = $ssoUser->expiresIn ?? null;
        $scopes = is_array($ssoUser['scp']) ? $ssoUser['scp'] : [$ssoUser['scp']];
    
        $user = User::updateOrCreate(
            ['character_id' => $characterId],
            [
                'avatar' => $avatar,
                'character_name' => $characterName,
                'character_owner_hash' => $characterOwnerHash,
                'token' => $token,
                'refresh_token' => $refreshToken,
                'expiresIn' => $expiresIn,
            ]
        );

        //Delete currently saved scopes, then add the scopes used to login with.
        EsiScope::where(['character_id' => $characterId])->delete();
        foreach($scopes as $scope) {
            $data = new EsiScope;
            $data->character_id = $characterId;
            $data->scope = $scope;
            $data->save();
        }

        //Add Esi Token to the token database
        $esiToken = EsiToken::updateOrCreate(
            ['character_id' => $characterId],
            [
                'access_token' => $token,
                'refresh_token' => $refreshToken,
                'inserted_at' => time(),
                'expires_in' => $expiresIn,
            ]
        );

        if (!UserRole::where(['character_id' => $characterId])->count() > 0) {
            $role = new UserRole;
            $role->character_id = $characterId;
            $role->role = 'Guest';
            $role->rank = 1;
            $role->save();
        }

        $privilege->privilegesChanged($user);

        //Send the object back to the calling function
        return $user;
    }
}
