<?php

namespace App\Modules\Admin\Verification;

use App\Models\AdminUser;

use App\Traits\MobileNumberValidatorTraits;
use App\Traits\SendSMSTraits;
use App\Traits\GenerateCodeTraits;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Hash;
use Carbon\Carbon;

class Verification{

    use SendSMSTraits, GenerateCodeTraits, MobileNumberValidatorTraits;

    public function verifyAdmin($payload){
        $rules = array(
            'email_address' =>'required|max:255|min:3',
            'password' =>'required|max:255|min:8',
        );

        $error = Validator::make($payload->all(), $rules);
        if($error->fails()){
            return response()->json(['errors' => $error->errors()->all()]);
        }

        /* Check Admin password match */
        $user = AdminUser::where('email_address', $payload->email_address)->first();
        
        if($user && !$user->email_verified_at){
            return response()->json([
                'errors' => ['Please verify your email address.']
            ], 201);
        }else if (!$user || !Hash::check($payload->password, $user->password)) {
            return response()->json([
                'errors' => ['These credentials do not match our records.']
            ], 201);
        }

        /* Check if Admin is being blocked */
        if($user->blocked_expiration){
            $time = $this->checkHourBlocked($user->blocked_expiration);
            if(!empty($time)){
                return response()->json([
                    'errors' => ['You have reached the maximum failed attempts. Account will be blocked for the mean time. Please try again in '. $time['minutes'] .' minutes.']
                ], 201);
            }
        }

        /* Check if 2FA is enabled */
        if($user->enable_2fa == 'true'){
            $mobile_code = strtoupper($this->get_rand_alphanumeric());

            /* Check code 1hr expiration, using minutes */
            if($user->mobile_code_expiration){
                $now = Carbon::now();   
                $expiration_hour =  Carbon::create($user->mobile_code_expiration);
                $difference = ($now)->diffInMinutes($expiration_hour, false); //false to return both nega&posi value  

                if($difference > 1){

                    /* Not yet expired, direct to login */
                    return response()->json(['success'=>'Execute login'], 201);

                }else{

                    /* Expired, resend new code */
                    $phone_message = $this->sendMessage($user->phone_num, '[ConX] Verification Code: '.$mobile_code);
                    $transaction = AdminUser::where('email_address', $payload->email_address)->update(['mobile_code' => $mobile_code]);
                    if($phone_message && $transaction){
                        return response()->json(['success'=>'Execute 2FA'], 201);
                    }
                }
            }else{

                /* No code, send new code */
                $phone_message = $this->sendMessage($user->phone_num, '[ConX] Verification Code: '.$mobile_code);
                $transaction = AdminUser::where('email_address', $payload->email_address)->update(['mobile_code' => $mobile_code]);
                if($phone_message && $transaction){
                    return response()->json(['success'=>'Execute 2FA'], 201);
                }
            }
                
        }else{
            return response()->json(['success'=>'Execute login'], 201);
        }
    }

    public function checkHourBlocked($blocked_at){
        $date_today = Carbon::now();         
        $blocked_at = Carbon::create($blocked_at);
        $hours = $blocked_at->diff($date_today)->format('%H');
        $minutes = ($date_today)->diffInMinutes($blocked_at, false); 

        if($minutes < 1){
            return null;
        }else{
            return array(
                'now' => $date_today,
                'blocked_at' => $blocked_at,
                'hours' => $hours,
                'minutes' => $minutes,
            );
        }
    }

    public function verifyCode($payload){
        $user = AdminUser::where('email_address', $payload->email_address)->first();
        if($user->mobile_code == $payload->input){
            $transaction = AdminUser::where('email_address', $payload->email_address)->update(['mobile_code_expiration' => Carbon::now()->addHour(), 'blocked_expiration' => null]);
            return response()->json(['success'=>'Execute login'], 201);
        }else{
            return response()->json(['errors' => 'Invalid verification Code']);
        }   
    }

    public function blockAdminAccount($payload){
        $transaction = AdminUser::where('email_address', $payload->email_address)->update(['blocked_expiration'=> Carbon::now()->addHour()]);
        if($transaction){
            return response()->json(['errors' => 'You have reached the maximum failed attempts. Account will be blocked for the mean time. Please try again in 60 minutes.']);
        }
    }

    public function resendVerificationCode($payload){
        $mobile_code = strtoupper($this->get_rand_alphanumeric());
        $user = AdminUser::select('phone_num')->where('email_address', $payload->email_address)->first();

        $phone_message = $this->sendMessage($user->phone_num, '[ConX] Verification Code: '.$mobile_code);
        $transaction = AdminUser::where('email_address', $payload->email_address)->update(['mobile_code' => $mobile_code]);
        
        if($phone_message && $transaction){
            return response()->json(['success'=>'Successfully sent'], 201);
        }else{
            return response()->json(['errors'=>'Please try again later'], 201);
        }
    }

    public function disable2fa(){
        
    }
}