<?php

namespace App\Services\APIs\RestaurantService;

use App\Models\ManageRestaurant;
use App\Models\ManageVoucherModel;
use Exception;
use Illuminate\Support\Facades\Auth;
use App\Models\IamPrincipal;
use App\Models\ManageState;

use App\Models\IamPrincipalOtp;
use App\Models\IamPrincipalRestaurantRole;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Hash;
use Throwable;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class RestAuthApiService
{
    public function viewresyaurant()
    {
        try {
            $data = ManageRestaurant::select('id', 'name', 'description', 'restaurant_id', 'address', 'image', 'bio', 'try_on_1', 'try_on_2', 'try_on_3', 'try_on_4', 'exclusion', 'latitude', 'longtitude')->where('is_active', 1)->get()->toArray();
            return $data;
        } catch (Exception $ex) {
            DB::rollBack();
            Log::error('Terms and condition Get service failed : ' . $ex->getMessage());
            return jsonResponseWithErrorMessageApi(__('auth.something_went_wrong'), 500);
        }
    }

    public function viewstates()
    {
        try {
            $data = ManageState::select('id', 'name')->where('is_active', 1)->get()->toArray();
            return $data;
        } catch (Exception $ex) {
            Log::error('List sate Get service failed : ' . $ex->getMessage());
            return jsonResponseWithErrorMessageApi(__('auth.something_went_wrong'), 500);
        }
    }
    public function restRegister($request)
    {
        try {
            DB::beginTransaction();
            $restaurantId = $request->input('restaurant_xid');

            // Fetch the restaurant details based on the selected restaurantId
            $selectedRestaurant = ManageRestaurant::find($restaurantId);

            if (!$selectedRestaurant) {
                return jsonResponseWithErrorMessageApi(__('auth.restaurant_data_not_found'), 403);
            }

            // Create a new restaurant user record
            $restaurantuser = IamPrincipal::create([
                'one_signal_player_id' => $request->one_signal_player_id,
                'first_name' => $request->first_name,
                'last_name' => $request->last_name,
                'email_address' => $request->email_address,
                // 'password' => Hash::make('Cheers@123'),
                'principal_type_xid' => 4, //4 for restaurant
                'principal_source_xid' => 2, //2 for mobile
                'phone_number' => $request->phone_number,
                'date_of_birth' => $request->date_of_birth,
                'is_active' => '0',
                // 'state_xid' => $request->state_xid
            ]);

            $restaurantUserRole = IamPrincipalRestaurantRole::create([
                'principal_xid' => $restaurantuser->id,
                'role' => $request->role,
                'restaurant_xid' => $restaurantId,
            ]);

            DB::commit();

            // $token = auth()->login($restaurantuser);

            // Return response with user details, access token, and status
            $response = [
                'user' => $restaurantuser,
                // 'restaurant_details' => $restaurantId,
                // 'access_token' => $token,
                'token_type' => 'bearer',
                'status' => 'Your request has been processed. Please check your email for further details.'
            ];
            return jsonResponseWithSuccessMessage(__('auth.Rest_user_created'), $response, 200);
        } catch (QueryException $e) {
            // Rollback transaction in case of an error
            DB::rollBack();
            Log::error('Restaurant Registration Failed ' . $e->getMessage());
            return jsonResponseWithErrorMessageApi(__('auth.authentication_failed'), 403);
        }
    }


    public function login($request)
    {
        try {
            $credentials = [
                'email_address' => $request->email_address,
                'password' => $request->password,
            ];

            $isExistEmail = IamPrincipal::where('email_address', $request->email_address)
                ->where('principal_type_xid', 4)
                ->whereNull('deleted_at')
                ->first();
            if ($isExistEmail == null) {
                Log::error('Email not exist');
                return jsonResponseWithErrorMessageApi(__('auth.incorrect_email_passport'), 403);
            }
            if ($isExistEmail && !(Hash::check($request->password, $isExistEmail->password))) {
                Log::error('Entered Password is wrong.');
                return jsonResponseWithErrorMessageApi(__('auth.incorrect_email_passport'), 403);
            }
            if (!$token = auth()->login($isExistEmail)) {
                Log::error('Customer Login Failed');
                return jsonResponseWithErrorMessageApi(__('auth.authentication_failed'), 403);
            }

            $isExistEmail->one_signal_player_id = $request->one_signal_player_id;
            $isExistEmail->save();
            $response = [
                'userId' => $isExistEmail->id,
                'access_token' => $token,
            ];
            return jsonResponseWithSuccessMessage(__('auth.data_fetched_successfully'), $response, 200);
        } catch (QueryException $e) {


            Log::error('Customer Login Failed ' . $e->getMessage());
            return jsonResponseWithErrorMessageApi(__('auth.authentication_failed'), 403);
        }
    }


    protected function responseWithToken($token, $isExistEmail)
    {
        return [
            'message' => 'You have logged in successfully',
            'access_token' => $token,
            'token_type' => 'bearer',
            'status' => 'success',
            'iam_principal_id' => $isExistEmail->id
        ];
    }


    public function restForgotPassword($request)
    {
        try {
            DB::beginTransaction();
            $user = IamPrincipal::where('email_address', $request->email_address)
                ->where('principal_type_xid', 4)
                ->whereNull('deleted_at')
                ->first();
            //use this for both customer and restaurant just change principal_type_xid 4
            if ($user == null) {
                Log::error('Email not exist');
                return jsonResponseWithErrorMessageApi(__('auth.incorrect_email'), 403);
            }
            // Define the generateOTP function
            $otp = $this->generateOTP();

            IamPrincipalOTP::updateOrCreate(
                ['principal_xid' => $user->id],
                [
                    'otp_code' => $otp,
                    'otp_purpose' => 'forgot password',
                    'valid_till' => Carbon::now()->addMinutes(2),
                    'is_used' => 0,
                ]
            );

            // $this->email_address = $user->email_address;

            $mail = Mail::send(
                'frontend.Mail.customer_forgot_password_mail',
                [
                    'user' => $user,
                    'otp_code' => $otp,
                    'valid_till' => Carbon::now()->addMinutes(2)
                ],
                function ($message) use ($user) {
                    $message->to($user->email_address);
                    $message->subject('Forgot Password Mail Page');
                }
            );

            //sendmail end
            $response = ['iam_principal_xid' => $user->id];
            DB::commit();
            Log::info('Customer Forgot Password otp sent successfully');
            return jsonResponseWithSuccessMessage(__('auth.otp_sent_successfully'), $response, 200);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Customer Forgot Password OTP function failed: ' . $e->getMessage());
            return jsonResponseWithErrorMessageApi(__('auth.something_went_wrong'), 500);
        }
    }

    public function restVerifyOTP($request)
    {
        try {
            DB::beginTransaction();
            // Retrieve the user's OTP record
            $User = IamPrincipal::where('email_address', $request->email_address)
                ->where('principal_type_xid', 4)
                ->whereNull('deleted_at')
                ->first();


            $iamPrincipal = IamPrincipalOTP::where('principal_xid', $User->id)
                ->first();

            // Check if OTP record exists for the user
            $errors = [];

            if (!$iamPrincipal) {
                $errors[] = __('auth.failed_to_verify_otp');
                return jsonResponseWithErrorMessageApi(
                    $errors,
                    403
                );
            }

            // Check if the provided OTP matches the stored OTP
            if ($iamPrincipal->otp_code !== $request->otp) {
                $errors[] = __('auth.invalid_otp');
                return jsonResponseWithErrorMessageApi(
                    $errors,
                    403
                );
            }

            // Check if the OTP is still valid
            if (Carbon::now()->gt($iamPrincipal->valid_till)) {
                $errors[] = __('auth.otp_expired');
                return jsonResponseWithErrorMessageApi(
                    $errors,
                    403
                );
            }

            // Check if the OTP has already been used
            if ($iamPrincipal->is_used === 1) {
                $errors[] = __('auth.otp_already_used');
                return jsonResponseWithErrorMessageApi(
                    $errors,
                    403
                );
            }



            // Mark OTP as used
            $iamPrincipal->is_used = 1;
            $iamPrincipal->save();
            DB::commit();
            $response = [
                'iam_principal_xid' => $User->id
            ];
            Log::info('Customer OTP verified successfully');
            return jsonResponseWithSuccessMessageApi(__('auth.otp_verified'), $response, 200);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error("An error occurred in " . __METHOD__ . ": " . $e->getMessage());
            return jsonResponseWithErrorMessageApi(__('auth.something_went_wrong'), 500);
        }
    }

    public function restChangePassword($request)
    {
        try {
            DB::beginTransaction();

            $User = IamPrincipal::where('id', $request->iam_principal_xid)
                ->where('is_active', 1)
                ->first();


            $User->password = Hash::make($request->password);
            $User->save();
            DB::commit();
            return $User;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error("An error occurred in " . __METHOD__ . ": " . $e->getMessage());
            return response()->json(__('something_went_wrong'), 500);
        }
    }
    public function restResendOtp($request)
    {
        try {
            DB::beginTransaction();
            // Retrieve the user's OTP record
            $iamPrincipal = IamPrincipalOTP::where('principal_xid', $request->iam_principal_xid)
                ->first();
            $user = IamPrincipal::where('id', $request->iam_principal_xid)
                ->where('is_active', '1')
                ->first();

            // Check if OTP record exists for the user
            if (!$iamPrincipal) {
                return jsonResponseWithErrorMessageApi(__('auth.not_found_otp'), 203);
            }

            // Calculate the allowed resend interval (2 minutes)
            $allowedResendInterval = Carbon::now()->subMinutes(2);

            // Check if the user can resend OTP only after a 2-minute interval
            if ($iamPrincipal->updated_at >= $allowedResendInterval) {

                return jsonResponseWithErrorMessageApi(__('auth.try_resend_otp'), 429);
            }

            // Generate a new OTP for the user
            $otp = $this->generateOTP();

            // Update the OTP record with the new OTP and validity
            $iamPrincipal->principal_xid = $request->iam_principal_xid;
            $iamPrincipal->otp_code = $otp;
            $iamPrincipal->otp_purpose = $request->otp_purpose;
            $iamPrincipal->valid_till = Carbon::now()->addMinutes(2);
            $iamPrincipal->is_used = 0;
            $iamPrincipal->save();


            // $this->email_address = $user->email_address;

            $mail = Mail::send(
                'frontend.Mail.customer_forgot_password_mail',
                [
                    'user' => $user,
                    'otp_code' => $otp,
                    'valid_till' => Carbon::now()->addMinutes(2)
                ],
                function ($message) use ($user) {
                    $message->to($user->email_address);
                    $message->subject('Forgot Password Mail Page');
                }
            );


            DB::commit();
            $response = [
                'iam_principal_xid' => $iamPrincipal->principal_xid,
                'email_address' => $user->email_address

            ];

            return jsonResponseWithSuccessMessageApi(__('auth.otp_resend_sent_successfully'), $response, 200);
        } catch (\Exception $e) {

            DB::rollBack();
            Log::error("An error occurred in " . __METHOD__ . ": " . $e->getMessage());
            return response()->json(__('something_went_wrong'), 500);
        }
    }

    function generateOTP()
    {
        // Define the length of the OTP
        $otpLength = 4;

        // Generate a random OTP with $otpLength digits
        $otp = '';
        for ($i = 0; $i < $otpLength; $i++) {
            $otp .= rand(0, 9);
        }
        return $otp;
    }



    public function searchRest($request)
    {
        try {
            $searchQuery = $request->input('search_data');

            $query = ManageRestaurant::select('id', 'name')->where('is_active', 1);

            if ($searchQuery) {
                $query->where(function ($q) use ($searchQuery) {
                    $q->where('name', 'like', '%' . $searchQuery . '%')
                        ->orWhere('address', 'like', '%' . $searchQuery . '%');
                });
            }
            $restaurants = $query->get();
            return jsonResponseWithSuccessMessageApi(__('auth.data_fetched_successfully'), $restaurants, 200);
        } catch (\Exception $e) {
            Log::error("An error occurred in " . __METHOD__ . ": " . $e->getMessage());
            return response()->json(__('something_went_wrong'), 500);
        }
    }
}
