<?php

namespace App\Http\Controllers\API;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use App\Http\Controllers\SMSController;
use App\Mail\OTP;
use Illuminate\Support\Facades\Mail;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Firebase\JWT\ExpiredException;
use App\Http\Controllers\XMPPController;
use App\Models\UserBooking;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;

class AuthController extends Controller
{
    // API Documenation for register
    function register(Request $request)
    {
        //validation
        $validator = Validator::make($request->all(), [
            'username' => 'required|string|unique:users|max:255',
            'email' => 'required|email|unique:users',
            'phone' => 'required|unique:users|regex:/^([0-9\s\-\+\(\)]*)$/|min:10',
            'otp' => 'required'
        ]);
        if($validator->fails()){
            return response()->json([
                'status' => false,
                'message' => $validator->errors()
            ]);
        }
      
        $otp = cache()->get("otp_$request->phone");
        $username = $request->username;
        if ($otp == $request->otp) {
          
            //    make xmpp password random string
            $xmpp_password = Str::random(12);
            $user = User::create([
                'username' => $username,
                'name' => "",
                'email' => $request->email,
                'phone' => $request->phone,
                'phone_verified_at' => now(),
                'password' => bcrypt($request->phone . "123")

            ]);
     
            // send otp to email
            $this->get_otp($request);

            // register to xmpp and get xmppid
            $xmpperror = "";
            //  $resp = $this->registerToXMPP($user->phone, "123456654");
            $phone = $user->phone;
            $phone = str_replace("+", "", $phone);

            $xmpp = new XMPPController();

            $xmpp_password = $xmpp_password != "" ? $xmpp_password : "123456644412";

            $resp = $xmpp->registerToXMPP($user->phone.'_'.$user->id, $xmpp_password);
            if ($resp == 1) {
                $user->xmppid = $phone . "_".$user->id."@xmpp.icoredeals.com";
                $user->xmpp_password = $xmpp_password;
                $user->save();
            } else {
                $xmpperror = $resp;
            }

            // $token = $user->createToken('authToken')->accessToken;

            return response()->json([
                //'xmpperror' => $xmpperror,
                'messager' => 'User created successfully. Verify your email',
            ]);
        } else {
            return response()->json([
                'message' => 'Invalid OTP'
            ], 401);
        }
    }

    // check username unique on keyup
    function check_username(Request $request)
    {
        //  dd($request->username);
        $user = User::where('username', $request->username)->first();

        // length of username
        if (strlen($request->username) < 4) {
            return response()->json([
                'status' => 'error',
                'message' => 'Username must be at least 4 characters'
            ], 401);
        }

        if ($user) {
            return response()->json([
                'status' => 'error',
                'message' => 'Username already taken'
            ], 401);
        } else {
            return response()->json([
                'status' => 'success',
                'message' => 'Username available'
            ]);
        }
    }


    public function userInfo()
    {
        $user = auth()->user();
        //get all pending review sessions
        $user_bookings = UserBooking::select('user_bookings.*','service_schedules.schedule_name','users.username','users.profile_picture')
                                    ->join('service_schedules','service_schedules.id','=','user_bookings.schedule_id')
                                    ->join('users','users.id','=','user_bookings.service_provider_id')
                                    ->where('customer_id',$user->id)
                                    ->where('to_date','<=',now())
                                    ->where('rating','=',null)
                                    ->where('review','=',null)
                                    ->get();
        
        $review_pending = [];
         if($user_bookings){
            foreach($user_bookings as $booking){
                $days = [];
                $daystring = date('D',strtotime($booking->date));
                $days[] = $this->get_daynum_from_daystring($daystring);

                $review_pending[] = array(
                    'id'                  => $booking->id,
                    'schedule_id'         => $booking->schedule_id,
                    'schedule_name'       => $booking->schedule_name,
                    'service_provider_id' => $booking->service_provider_id,
                    'username'            => $booking->username,
                    // url('storage/profile_image/'.$user->profile_picture),
                    'profile_picture'     => url('storage/profile_image/'.$booking->profile_picture),
                    'days'                => $days,
                    'date'                => $booking->date,
                    'to_date'             => $booking->to_date,
                    'start_time'          => $booking->start_time,
                    'end_time'            => $booking->end_time
                );
            }
         }
        return response()->json(['user' => $user,'pending_reviews'=>$review_pending], 200);
    }

    //get_daynum_from_daystring
   public function get_daynum_from_daystring($daystring)
   {
      if($daystring == "Sun" || $daystring == "sun"){
         $day_num = 0;
      }elseif($daystring == "Mon" || $daystring == "mon"){
        $day_num = 1;
      }elseif($daystring == "Tue" || $daystring == "tue"){
        $day_num  = 2;
      }elseif($daystring == "Wed" || $daystring == "wed"){
        $day_num = 3;
      }elseif($daystring == "Thu" || $daystring == "thu"){
        $day_num = 4;
      }elseif($daystring == "Fri" || $daystring == "fri"){
        $day_num = 5;
      }elseif($daystring == "Sat" || $daystring == "sat"){
        $day_num = 6;
      }
      return $day_num;
   }


    public function get_otp(Request $request)
    {
        $this->validate($request, [
            'email' => 'required',
        ]);

        /// identify value is email or phone
        if (filter_var($request->email, FILTER_VALIDATE_EMAIL)) {
            $user = User::where('email', $request->email)->first();
            $otp = $this->send_otp($request->email, "email");
            //send email
        } else {

            $user = User::where('phone', $request->email)->first();
            $otp = $this->send_otp($request->email, "sms");
        }

        if ($user) {
            return response()->json(['message' => 'OTP sent', 'action' => 'login', 'otp' => $otp], 200);
        } else {
            return response()->json(['message' => 'OTP sent', 'otp' => $otp, 'action' => 'register'], 404);
        }
    }

    public function send_otp($user, $method = "sms")
    {
        $otp = rand(100000, 999999);
        if ($method == "sms") {

            $message = 'Your OTP for DSR Silks and Sarees login is ' . $otp . '.The OTP is valid for only 10 mins .';
            $phone = $user;
            $sms = new SMSController();
            // $sms->send($phone, $message);

            // write to cache
            cache()->put("otp_$phone", $otp, now()->addMinutes(30));
        } else {
            // $otp
            Mail::to($user)->send(new OTP($otp));
            cache()->put("otp_$user", $otp, now()->addMinutes(30));
        }
        return $otp;
    }

    public function verify_otp(Request $request)
    {

        $this->validate($request, [
            // required email or phone
            'email' => 'required',
            'otp' => 'required',
            'device_id' => 'required',
        ]);

        $phone = "";
        $email = "";
        if (filter_var($request->email, FILTER_VALIDATE_EMAIL)) {
            $email = $request->email;
        } else {
            $phone = $request->email;
        }

      
        $user = NULL;
        if ($phone != "") {
            //$phone = $phone;
            $user = User::where('phone', $phone)->first();
        } else if ($email != "") {
            // $email = $email;
            $user = User::where('email', $email)->first();
        } else {
            return response()->json(['message' => 'Invalid email or phone'], 404);
        }
  
        if ($user) {

            $firsttimeLogin = true;
            // user has profile ?
            if ($user->profile) {
                $firsttimeLogin = false;
            }


            $otp = cache()->get("otp_$request->email");

            // if (!$otp) {
            //     $otp = cache()->get("otp_$user->phone");
            // }
            
            if ($otp == $request->otp) {
              
                if($user->account_status != "login"  || $user->account_status == ""){
                    if ($email && $firsttimeLogin) {
                        $user->email_verified_at = now();
                    }
                    if ($phone && $firsttimeLogin) {
                        $user->phone_verified_at = now();
                    }
                    $user->account_status = "login";
                    $user->last_login = date('Y-m-d H:i:s');
                    $user->device_id = $request->device_id;
                    $user->save();
                    $token = $user->createToken('authToken')->accessToken;
                   
                    return response()->json(['token' => $token, 'firstlogin' => $firsttimeLogin, 'token_type' => 'Bearer'], 200);
                }else{
                    return response()->json(['message' => 'Already logged in another device'], 200);
                }
                
            } else {
                return response()->json(['message' => 'Invalid OTP'], 401);
            }
        } else {
            $otp = cache()->get("otp_$email");

            if (!$otp) {
                $otp = cache()->get("otp_$phone");
            }
            if ($otp == $request->otp) {

                // clear otp
                // cache()->forget("otp_$email");
                // cache()->forget("otp_$phone");


                return response()->json(['message' => 'Phone number verified', 'action' => 'register'], 200);
            } else {
                return response()->json(['message' => 'Invalid OTP'], 401);
            }
        }
    }




    public function social_login(Request $request)
    {
        $this->validate($request, [
            'email' => 'required',
            'name' => 'required',
            'provider' => 'required',
            'provider_id' => 'required',
        ]);


        $user = User::where('email', $request->email)->first();
        if ($user) {
            $token = $user->createToken('authToken')->accessToken;
            return response()->json(
                ['token' => $token, 'token_type' => 'Bearer'],
                200
            );
        } else {
            $user = User::create([
                'name' => $request->name,
                'email' => $request->email,
                'password' => bcrypt($request->email . "123"),
                'provider' => $request->provider,
                'provider_id' => $request->provider_id,
            ]);
            $token = $user->createToken('authToken')->accessToken;
            return response()->json(
                ['token' => $token, 'token_type' => 'Bearer'],
                200
            );
        }
    }

    public function login_otp(Request $request)
    {
        $this->validate($request, [
            'email' => 'required',
            'device_id' => 'required',
        ]);


        // get user by email or phone
        $user = User::where('email', $request->email)->orWhere('phone', $request->email)->first();
       
        if (!$user) {
            return response()->json(['message' => 'User not found', 'status' => 'error'], 404);
        }
        
        if($user->account_status == "login" && $user->device_id == $request->device_id){
            $user->account_status = null;
            $user->save();
        }
        if($user->account_status == "login" && $user->device_id != $request->device_id){
            return response()->json(['message' => 'Already logged in another device'], 200);
        }
        /// identify value is email or phone
        if (filter_var($request->email, FILTER_VALIDATE_EMAIL)) {
            $user = User::where('email', $request->email)->first();
            $otp = $this->send_otp($request->email, "email");
            //send email
        } else {
            $user = User::where('phone', $request->email)->first();
            $otp = $this->send_otp($request->email, "sms");
        }

        if ($user) {
            return response()->json(['message' => 'OTP sent', 'action' => 'login', 'otp' => $otp], 200);
        } else {
            return response()->json(['message' => 'OTP sent', 'otp' => $otp, 'action' => 'register'], 404);
        }
    }

    public function logout(Request $request)
    {
      $user = User::find(Auth::user()->id);
      $user->account_status = null;
      $user->save();
      return response()->json(['message' => 'Logout successfully'], 200);
    }

    //logout_all_send_otp
    public function logout_all_send_otp(Request $request){
        $otp = rand(100000, 999999);
        
        if($request->phone != ""){

            $user = User::where('phone',$request->phone)->first();
            Cache::forget('logout_otp');
            Cache::add('logout_otp',$otp,now()->addMinutes(30));
           
            if($user){
                return response()->json(['message' => 'OTP sent ! OTP will expire after 30 mins', 'otp' => $otp, 'action' => 'logout_all'], 200);
            }else{
                return response()->json(['message' => 'User not found', 'status' => 'error'], 404);
            }
        }else{
            return response()->json(['message' => 'Invalid email or phone'], 404);
        }
    }

    // /logout_all_verity_otp
    public function logout_all_verity_otp(Request $request){
        if($request->phone != ""){
            
                  $user = User::where('phone',$request->phone)->first();
                  if($user){
                      $user->account_status = null;
                      $user->save();

                      return response(['message' => 'Logout successfully']);
                  }else{
                      return response(['status' => 'error', 'message' => 'User not found']);
                  }    
      }
      die;
      //otp verification ignored
        $cache_otp = Cache::get('logout_otp');
        if($request->phone != "" && $request->otp != ""){
              if($request->otp == $cache_otp){
                    $user = User::where('phone',$request->phone)->first();
                    if($user){
                        $user->account_status = null;
                        $user->save();

                        return response(['message' => 'Logout successfully']);
                    }else{
                        return response(['status' => 'error', 'message' => 'User not found']);
                    }
              }else{
                return response(['status' => 'error', 'message' => 'Invalid OTP']);
              }
        }else{
            return response(['status' => 'error', 'message' => 'Requires fields are missing']);
        }
    }
}
