<?php

namespace App\Http\Controllers\Auth;

use App\Enums\StatusEnum;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\AuthenticateRequest;
use App\Http\Services\Auth\AuthService;
use App\Models\User;
use App\Models\Workspace;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;


class LoginController extends Controller
{

    private $maxLoginAttempts, $lockoutTime, $authService;
    public function __construct()
    {

        $this->authService = new AuthService();
        $this->maxLoginAttempts = 1000;
        $this->lockoutTime = 2 * 60;
    }

    /**
     * Summary of login
     * @return \Inertia\Response
     */
    public function login()
    {
        $appMode = env('APP_MODE', 'live');
        $demoCredentials = null;

        if ($appMode === 'demo') {
            $demoCredentials = [
                'username' => env('DEMO_USERNAME', ''),
                'password' => env('DEMO_PASSWORD', '')
            ];
        }

        return Inertia::render('Auth/Login', [
            'app_mode' => $appMode,
            'demo_credentials' => $demoCredentials
        ]);
    }


    /**
     * Authenticate a user
     *
     * @param AuthenticateRequest $request
     * @return RedirectResponse
     */
    public function authenticate(AuthenticateRequest $request): RedirectResponse
    {
        $field = $this->getLoginField($request->input('loginIdentifier'));
        $rules = $this->getLoginRules($request->input('loginIdentifier'));


        $request->validate([
            'loginIdentifier' => $rules,
            'password' => ['required', 'string'],
        ], [
            'loginIdentifier.exists' => 'These credentials do not match our records.',
        ]);

        $remember_me = $request->has('remember_me');
        $credentials = [$field => request()->input('loginIdentifier'), 'password' => request()->input('password')];


        if ($this->authService->loginWithOtp()) {
            $user = User::where("phone", request()->input('loginIdentifier'))->first();

            if ($user && $this->authService->otpConfiguration($user))
                return redirect(route('auth.otp.verification'))
                    ->with(response_status('Check your phone! An OTP has been sent successfully.'));

            return redirect()->back()->with(response_status("Invalid credential", "error"));
        }


        if (Auth::guard('web')->attempt($credentials, $remember_me)) {

            $this->onSuccessfulLogin($request, $field);
            return redirect()->route('user.home')->with(response_status('Login success'));
        }

        return redirect()->back()->with(response_status("Invalid credential", "error"));
    }



    private function onSuccessfulLogin(AuthenticateRequest $request, string $field): void
    {
        $user               = auth_user('web');
        $defaultWorkspace   = Workspace::where('is_default' , StatusEnum::true->status())->first();
        $user->last_login   = Carbon::now();
        $user->current_workspace_id = $defaultWorkspace->id;
        $user->save();
    }



    /**
     * get login filed
     * @param string $login
     * @return string
     */
    public function getLoginField(string $login): string
    {

        if (filter_var($login, FILTER_VALIDATE_EMAIL)) {
            return 'email';
        } elseif (preg_match('/^[0-9]+$/', $login)) {
            return 'phone';
        }
        return 'username';
    }

    public function getLoginRules(string $login): array
    {
        if (filter_var($login, FILTER_VALIDATE_EMAIL)) {
            $field = 'email';
            $rules = ['required', 'email', 'exists:users,email'];
        } elseif (preg_match('/^[0-9]{10,15}$/', $login)) {
            $field = 'phone';
            $rules = ['required', 'exists:users,phone'];
        } else {
            $field = 'username';
            $rules = ['required', 'exists:users,username'];
        }

        return $rules;
    }


    protected function hasTooManyLoginAttempts(Request $request, string $field)
    {
        return RateLimiter::tooManyAttempts($this->throttleKey($request, $field), $this->maxLoginAttempts);
    }

    /**
     *
     * @param Request $request
     * @param string $field
     * @return string
     */
    protected function throttleKey(Request $request, string $field): string
    {
        return $field . '|' . $request->ip();
    }


    /**
     * send lockout response
     *
     * @param Request $request
     * @param string $field
     * @return RedirectResponse
     */
    protected function sendLockoutResponse(Request $request, string $field): RedirectResponse
    {
        $seconds = RateLimiter::availableIn($this->throttleKey($request, $field));
        $minutes = ceil($seconds / 60);
        return redirect()->back()->with(
            'error',
            translate("Too many login attempts!! Please try again after ") . $minutes . ' minute '
        );
    }

    protected function incrementLoginAttempts(Request $request, string $field)
    {
        RateLimiter::hit($this->throttleKey($request, $field), $this->lockoutTime);
    }

    /**
     * clear login attempts
     * @param Request $request
     * @param string $field
     * @return void
     */
    protected function clearLoginAttempts(Request $request, string $field)
    {
        RateLimiter::clear($this->throttleKey($request, $field));
    }

    /**
     * logout method
     *
     * @return RedirectResponse
     */
    public function logout(): RedirectResponse
    {

        Auth::guard('web')->logout();
        return redirect()->route('auth.login');
    }
}
