<?php

namespace App\Http\Controllers\User\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Apptitle;
use Hash;
use Auth;
use App\Traits\SocialAuthSettings;
use Laravel\Socialite\Facades\Socialite;
use App\Models\SocialAuthSetting;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use App\Models\Customer;
use Carbon\Carbon;
use Response;
use GeoIP;
use App\Models\Announcement;
use App\Models\VerifyUser;
use App\Models\VerifyOtp;
use PragmaRX\Google2FA\Google2FA;
use App\Models\CustomerSetting;
use App\Models\User;
use App\Models\Holiday;
use laravelLara\infoinst\Jobs\MailSend;

class LoginController extends Controller

{
    use SocialAuthSettings, ThrottlesLogins, AuthenticatesUsers;

    public function showLoginForm()
    {

        $data['setting'] = response()->json(['only_social_logins' => setting('only_social_logins'), 'login_disable' => setting('login_disable'), 'login_disable_statement' => setting('login_disable_statement'), 'CAPTCHATYPE' => setting('CAPTCHATYPE'), 'RECAPTCH_ENABLE_LOGIN' => setting('RECAPTCH_ENABLE_LOGIN'), 'REGISTER_DISABLE' => setting('REGISTER_DISABLE'), 'GOOGLE_RECAPTCHA_KEY' => setting('GOOGLE_RECAPTCHA_KEY'), 'ANNOUNCEMENT_USER' => setting('ANNOUNCEMENT_USER')]);

        $socialAuthSettings = SocialAuthSetting::first();
        $data['socialAuthSettings'] = $socialAuthSettings;

        $title = Apptitle::first();
        $data['title'] = $title;

        $now = now();
        $announcement = announcement::whereDate('enddate', '>=', $now->toDateString())->whereDate('startdate', '<=', $now->toDateString())->get();
        $data['announcement'] = $announcement;

        $announcements = Announcement::whereNotNull('announcementday')->get();
        $data['announcements'] = $announcements;

        // $holidays = Holiday::whereDate('startdate', '<=', $now->toDateString())->whereDate('enddate', '>=', $now->toDateString())->where('status', '1')->get();
        // $data['holidays'] =  $holidays;

        $now = now();
        $currentYear = $now->year;
        $activeHolidays = Holiday::where('status', 1)->get();
        $data['holidays'] = $activeHolidays->filter(function ($holiday) use ($now, $currentYear) {
            $holidayStart = Carbon::parse($holiday->startdate);
            $holidayEnd = Carbon::parse($holiday->enddate);
            if ($holiday->is_fixed) {
                return $holidayStart->month === $now->month && $holidayStart->day === $now->day;
            }
            return $holidayStart->isSameDay($now);
        });

        return $data;
    }

    public function emailverification(Request $request)
    {
        $socialAuthSettings = SocialAuthSetting::first();
        $data['socialAuthSettings'] = $socialAuthSettings;

        $now = now();
        $announcement = announcement::whereDate('enddate', '>=', $now->toDateString())->whereDate('startdate', '<=', $now->toDateString())->get();
        $data['announcement'] = $announcement;

        $announcements = Announcement::whereNotNull('announcementday')->get();
        $data['announcements'] = $announcements;
        // $holidays = Holiday::whereDate('startdate', '<=', $now->toDateString())->whereDate('enddate', '>=', $now->toDateString())->where('status', '1')->get();
        // $data['holidays'] =  $holidays;

        $now = now();
        $currentYear = $now->year;
        $activeHolidays = Holiday::where('status', 1)->get();

        $data['holidays'] = $activeHolidays->filter(function ($holiday) use ($now, $currentYear) {
            $holidayStart = Carbon::parse($holiday->startdate);
            $holidayEnd = Carbon::parse($holiday->enddate);
            if ($holiday->is_fixed) {
                return $holidayStart->month === $now->month && $holidayStart->day === $now->day;
            }
            return $holidayStart->isSameDay($now);
        });


        return $data;
    }
    public function login(Request $request)
    {
        $email = $request->email;
        $completeDomain = substr(strrchr($email, "@"), 1);
        $emaildomainlist = setting('EMAILDOMAIN_LIST');

        if ($emaildomainlist != null) {
            $emaildomainlistArray = explode(",", $emaildomainlist);
            if (setting('EMAILDOMAIN_BLOCKTYPE') == 'blockemail') {
                if (in_array($completeDomain, $emaildomainlistArray)) {
                    return response()->json(['error' => 'Your domain is blocked.']);
                }
            }

            if (setting('EMAILDOMAIN_BLOCKTYPE') == 'allowemail') {
                if (!in_array($completeDomain, $emaildomainlistArray)) {
                    return response()->json(['error' => 'Your domain is blocked.']);
                }
            }
        }
        if (setting('login_disable') == 'off') {


            if (setting('CAPTCHATYPE') == 'off') {
                $request->validate([
                    'email'     => 'required|exists:customers|max:255',
                    'password'  => 'required|min:6|max:255',

                ]);
            } else {
                if (setting('CAPTCHATYPE') == 'manual') {
                    if (setting('RECAPTCH_ENABLE_LOGIN') == 'yes') {
                        $this->validate($request, [
                            'email'     => 'required|exists:customers|max:255',
                            'password'  => 'required|min:6|max:255',
                            'captcha' => 'required',

                        ]);
                    } else {
                        $this->validate($request, [
                            'email'     => 'required|exists:customers|max:255',
                            'password'  => 'required|min:6|max:255',
                        ]);
                    }
                }
                if (setting('CAPTCHATYPE') == 'google') {
                    if (setting('RECAPTCH_ENABLE_LOGIN') == 'yes') {
                        $this->validate($request, [
                            'email'     => 'required|exists:customers|max:255',
                            'password'  => 'required|min:6|max:255',
                            'g-recaptcha-response' => 'required|recaptcha',


                        ]);
                    } else {
                        $this->validate($request, [
                            'email'     => 'required|exists:customers|max:255',
                            'password'  => 'required|min:6|max:255',
                        ]);
                    }
                }
            }

            $credentials  = $request->only('email', 'password');
            $customerExist = Customer::where(['email' => $request->email, 'status' => 0])->exists();

            if ($customerExist) {
                return response()->json(['error' => 'The account has been deactivated.']);
            }

            $unverifiedCustomer = Customer::where('email', $request->email)->first();

            if (setting('cust_email_verification') == 'on') {
                if (!empty($unverifiedCustomer) && $unverifiedCustomer->verified == 0) {
                    $this->emailverificationstore($request);
                    return response()->json(['error' => 'Your email has not been verified. Please verify your email.']);
                }
            }
            if (empty($unverifiedCustomer)) {
                return response()->json(['error' => 'This email is not registered.']);
            }

            if (Auth::guard('customer')->attempt($credentials)) {

                $cust = Customer::find(Auth::guard('customer')->id());
                $geolocation = GeoIP::getLocation(request()->getClientIp());
                $cust->update([
                    'last_login_at' => Carbon::now()->toDateTimeString(),
                    'last_login_ip' => $geolocation->ip,
                    'last_logins_at' => Carbon::now()->toDateTimeString(),
                ]);
                $redirectionstatus = null;
                if (setting('Customer_email_two_fact') == 'on' && CustomerSetting::where(['custs_id' => Auth::guard('customer')->user()->id, 'twofactorauth' => 'emailtwofact'])->exists()) {
                    if (!(session()->get('twofactoremail') == Auth::guard('customer')->user()->email)) {
                        $redirectionstatus = 'twofactoremail';
                    }
                } elseif (setting('Customer_google_two_fact') == 'on' && CustomerSetting::where(['custs_id' => Auth::guard('customer')->user()->id, 'twofactorauth' => 'googletwofact'])->exists()) {
                    if (!(session()->get('googleauthid') == Auth::guard('customer')->user()->email)) {
                        $redirectionstatus = 'googletwofact';
                    }
                }
                $request->session()->put('customerticket', Auth::id());
                return response(['success' => 'Login successful', "email" => $cust->email, 'redirectionstatus' => $redirectionstatus]);
            }

            return response()->json(['error' => 'Invalid email or password']);
        } else {
            return response()->json(['email' => 'Techincal Issue']);
        }
    }


    public function logout()
    {
        if (request()->session()->has('googleauthid')) {
            request()->session()->forget('googleauthid');
        }
        if (request()->session()->has('google2faemail')) {
            request()->session()->forget('google2faemail');
        }
        if (request()->session()->has('twofactoremail')) {
            request()->session()->forget('twofactoremail');
        }
        if (request()->session()->has('customerticket')) {
            request()->session()->forget('customerticket');
        }

        Auth::guard('customer')->logout();
        if (setting('REGISTER_POPUP') == 'yes' && setting('defaultlogin_on') != 'on') {
            return response()->json(['success' => 'Logout Successfully', 'redirect' => '/home']);
        } else {
            return response()->json(['success' => 'Logout Successfully']);
        }
    }

    // Social Login

    public function socialLogin($social)
    {
        $this->setSocailAuthConfigs();

        return Socialite::driver($social)->redirect();
    }
    /**
     * Obtain the user information from Social Logged in.
     * @param $social
     * @return Response
     */
    public function handleProviderCallback($social)
    {
        $this->setSocailAuthConfigs();
        $user = Socialite::driver($social)->user();
        $this->registerOrLogin($user, $social);

        $url = url('/customer/dashboard');
        return redirect()->away($url);
    }

    protected function registerOrLogin($data, $social)
    {

        $user = Customer::where('email', '=', $data->email)->first();
        if (!$user) {
            $user = new Customer();


            if ($social == 'google') {
                $user->firstname = $data->user['given_name'];
                $user->lastname = $data->user['family_name'];
                $user->username = $data->name;
                $user->logintype = 'googlesociallogin';
            }

            if ($social == 'envato') {
                $user->firstname = $data->user['firstname'];
                $user->lastname = $data->user['surname'];
                $user->username = $data->nickname;
                $user->logintype = 'envatosociallogin';
            }

            if ($social == 'microsoft') {
                $user->firstname = $data->user['givenName'];
                $user->lastname = $data->user['surname'];
                $user->username = $data->name;
                $user->logintype = 'microsoftsociallogin';
            }

            $user->email = $data->email;
            $user->provider_id = $data->id;
            $user->status = '1';
            $user->verified = '1';
            $user->userType = 'Customer';
            $user->save();
            
            $customersetting = new CustomerSetting();
            $customersetting->custs_id = $user->id;
            $customersetting->save();
        }

        if ($user->logintype == null) {
            $user->logintype = 'sociallogin';
            $user->save();
        }
        $geolocation = GeoIP::getLocation(request()->getClientIp());
        $user->last_login_ip = $geolocation->ip;
        $user->country = $geolocation->country;
        $user->timezone = $geolocation->timezone;
        $user->save();
        Auth::guard('customer')->login($user);
    }

    public function sessionLogout(Request $request)
    {
        if ($request->stayin == true) {
            $user = Auth::guard('customer')->user();
            $user->last_activity = now();
            $user->save();

            return response(1);
        } else {
            $user = Auth::guard('customer')->user();
            $user->last_activity = null;
            $user->save();
            if (request()->session()->has('googleauthid')) {
                request()->session()->forget('googleauthid');
            }
            if (request()->session()->has('google2faemail')) {
                request()->session()->forget('google2faemail');
            }
            if (request()->session()->has('twofactoremail')) {
                request()->session()->forget('twofactoremail');
            }
            if (request()->session()->has('customerticket')) {
                request()->session()->forget('customerticket');
            }

            Auth::guard('customer')->logout();

            return response()->json(['success' => 'Logged Out successfully.']);
        }
    }

    public function emailverificationstore(Request $request)
    {
        $user = Customer::where('email', '=', $request->email)->first();

        $existVerifyUser = VerifyUser::where('cust_id', $user->id)->get();
        if ($existVerifyUser != null) {
            foreach ($existVerifyUser as $existVerifyUsers) {
                $existVerifyUsers->delete();
            }
        }

        $verifyUser = VerifyUser::create([
            'cust_id' => $user->id,
            'token' => sha1(time())
        ]);

        $verifyData = [
            'username' => $user->username,
            'email' => $user->email,
            'email_verify_url' => url('/customer/user/verify/' . $verifyUser->token),
        ];

        try {
            dispatch((new MailSend($user->email, 'customer_sendmail_verification', $verifyData)));
        } catch (\Exception $e) {

            return Response::json(['success' => 'The email verification link was successfully sent. Please check and verify your email.']);
        }
        return Response::json(['success' => 'The email verification link was successfully sent. Please check and verify your email.']);
    }


    public function verifytwofactor(Request $request, $email)
    {
        $now = now();
        $announcement = announcement::whereDate('enddate', '>=', $now->toDateString())->whereDate('startdate', '<=', $now->toDateString())->get();
        $data['announcement'] = $announcement;

        $holidays = Holiday::whereDate('startdate', '<=', $now->toDateString())->whereDate('enddate', '>=', $now->toDateString())->where('status', '1')->get();
        $data['holidays'] =  $holidays;

        $setting =  response()->json([
            'ANNOUNCEMENT_USER' => setting('ANNOUNCEMENT_USER'),
            'defaultlogin_on' => setting('defaultlogin_on'),
            'KNOWLEDGE_ENABLE' => setting('KNOWLEDGE_ENABLE'),
            'FAQ_ENABLE' => setting('FAQ_ENABLE'),
            'CONTACT_ENABLE' => setting('CONTACT_ENABLE'),
            'REGISTER_POPUP' => setting('REGISTER_POPUP'),
            'REGISTER_DISABLE' => setting('REGISTER_DISABLE'),
            'GUEST_TICKET' => setting('GUEST_TICKET'),
            'login_disable' => setting('login_disable'),
            'login_disable_statement' => setting('login_disable_statement'),
            'terms_url' => setting('terms_url'),
            'CAPTCHATYPE' => setting('CAPTCHATYPE'),
            'RECAPTCH_ENABLE_REGISTER' => setting('RECAPTCH_ENABLE_REGISTER'),
            'RECAPTCH_ENABLE_LOGIN' => setting('RECAPTCH_ENABLE_LOGIN'),
            'GOOGLE_RECAPTCHA_KEY' => setting('GOOGLE_RECAPTCHA_KEY'),
            'theme_color' => setting('theme_color'),
            'theme_color_dark' => setting('theme_color_dark')
        ]);
        $data['setting'] = $setting;

        $announcements = Announcement::whereNotNull('announcementday')->get();
        $data['announcements'] = $announcements;

        $data['email'] = $email;

        if (session()->get('twofactoremail') == Auth::guard('customer')->user()->email) {
            return response(['success' => 'Already LoggedIn']);
        }

        $verifyotp = VerifyOtp::where('cust_id', $request->email)->first();
        if (!$verifyotp) {
            $verifyOtp = VerifyOtp::create([
                'cust_id' => $email,
                'otp' => rand(100000, 999999),
                'type' => 'twofactorotp',
            ]);

            $guestticket = [

                'otp' => $verifyOtp->otp,
                'guestemail' => $verifyOtp->cust_id,
                'guestname' => 'customer',
            ];
            try {
                dispatch((new MailSend($verifyOtp->cust_id, 'two_factor_authentication_otp_send', $guestticket)));
            } catch (\Exception $e) {
            }
        }
        return $data;
    }

    public function resendotp(Request $request)
    {
        if ($request->session()->has('twofactoremail')) {
            return response()->json(['success' => 'Success']);
        }

        $verifyUser = VerifyOtp::where('cust_id', $request->email)->first();
        if ($verifyUser) {
            $verifyUser->otp = rand(100000, 999999);
            $verifyUser->update();
        }

        $guestticket = [
            'otp' => $verifyUser->otp,
            'guestemail' => $verifyUser->cust_id,
            'guestname' => 'customer',
        ];
        try {
            dispatch((new MailSend($verifyUser->cust_id, 'two_factor_authentication_otp_send', $guestticket)));
        } catch (\Exception $e) {

            // return response()->json(['success' => lang('Please check your Email', 'alerts'), 'email' => 'exists']);
        }
        return response()->json(['success' => 'Please check your Email']);
    }

    public function otpverify(Request $request)
    {
        $verifyUser = VerifyOtp::where('cust_id', $request->email)->where('otp', $request->otp)->first();
        // if ($request->session()->has('twofactoremail')) {
        //     return response()->json(['success' => 'Success']);
        // }
        // if (User::where(['id' => Auth::id(), 'twofactorauth' => 'emailtwofact'])->exists()) {
        //     if ($request->session()->has('admintwofactoremail')) {
        //         return response()->json(['success' => 'Success']);
        //     }
        // }
        if ($verifyUser) {
            $verifyUser->delete();
            if (User::where(['id' => Auth::id(), 'twofactorauth' => 'emailtwofact'])->exists()) {
                session()->put('admintwofactoremail', $request->email);
                return response()->json(['success' => 'Success']);
            }
            $twofactor = session()->put('twofactoremail', $request->email);
            return response()->json(['success' => 'Success']);
        } else {
            return response()->json(['error' => 'Invalid otp.']);
        }
    }


    public function google2fa($email)
    {
        $socialAuthSettings = SocialAuthSetting::first();
        $data['socialAuthSettings'] = $socialAuthSettings;

        $now = now();
        $announcement = announcement::whereDate('enddate', '>=', $now->toDateString())->whereDate('startdate', '<=', $now->toDateString())->get();
        $data['announcement'] = $announcement;

        $announcements = Announcement::whereNotNull('announcementday')->get();
        $data['announcements'] = $announcements;

        $holidays = Holiday::whereDate('startdate', '<=', $now->toDateString())->whereDate('enddate', '>=', $now->toDateString())->where('status', '1')->get();
        $data['holidays'] =  $holidays;

        if (session()->has('googleauthid')) {
            return response(['success' => 'Already LoggedIn']);
        }
        if (!session()->has('google2faemail')) {
            session()->put('google2faemail', $email);
        }

        $data['email'] = session()->get('google2faemail');

        return $data;
    }

    public function google2fapage(Request $request)
    {
        $user = Customer::find($request->cust_id);
        if (!Hash::check($request->password, $user->password)) {
            return response()->json(['error' => 'You entered an invalid password.', 'message' => 'wrongpassword']);
        } else {
            if ($request->twofactor == 1) {
                $google2fa = app('pragmarx.google2fa');
                $google2fa_secret = $google2fa->generateSecretKey();
                $email = $user->email;
                $domainname = parse_url(url('/'));
                $request->session()->put('google2faemail', $email);
                $QR_Image = $google2fa->getQRCodeInline(
                    $domainname['host'],
                    config('app.name'),
                    $google2fa_secret
                );

                return response()->json(['success' => 'Scan And Activate your two factor authentication', 'QR_Image' => $QR_Image, 'secret' => $google2fa_secret, 'workprogress' => 'workingmode']);
            } else {

                $user->update(['google2fa_secret' => null,]);

                $custset = CustomerSetting::where('custs_id', $user->id)->first();
                $custset->twofactorauth = null;
                $custset->update();

                return response()->json(['success' => 'successfully disabled your two factor authentication.', 'workprogress' => 'notworkingmode']);
            }
        }
    }

    public function google2faotpverifylogin(Request $request)
    {

        $otp = (string) $request->one_time_password;
        if ($request->id) {
            $user = Customer::find($request->id);
        }

        if (session()->get('google2faemail')) {
            $user = Customer::where('email', '=', session()->get('google2faemail'))->first();
        }
        $google = decrypt($user->google2fa_secret);

        $google2fa = new Google2FA();
        $isValidOTP = $google2fa->verifyKey($google, $otp, 0);

        if ($isValidOTP) {
            $request->session()->put('googleauthid', $user->email);
            return response()->json(['success' => 'Success']);
        } else {
            return response()->json(['error' => 'Invalid otp.']);
        }
    }
}
