<?php

namespace App\Modules\Company\Account;

use App\Modules\Company\Account\Account;
use App\Modules\SMS\SendSMSViaTwilio;

use App\Models\Worker;
use App\Models\EmailVerification;

use App\Jobs\Company\ProcessSendEmailUpdateVerification;
use App\Jobs\Company\ProcessEmailVerificationCode;
use App\Jobs\Company\ProcessMobileUpdateNotificationEmail;

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Intervention\Image\Facades\Image;
use App\Traits\GoogleBucket;
use App\Modules\RemoteStorage\GoogleBucketGateway;

class Profile extends Account
{
    use GoogleBucket;

    public $googleBucket;
    public $userData;
    public function __construct(GoogleBucketGateway $googleBucket)
    {
        $this->googleBucket = $googleBucket;
        $this->twilio = new SendSMSViaTwilio;
        $this->userData = Auth::user();
    }
   
    public function update($id, $payload){     
        
        $rules = array(
           'email_address' =>'required|unique:workers,email_address,'.$id.'|max:191',
           'phone_num' =>'required|max:50',
           'first_name' => 'required|max:50',
           'last_name' => 'required|max:50',
       );
       $validate = $this->validateRequest($payload, $rules);
       if ($validate) {
           return $validate;
       }

       $validate = $this->validatePhoneNumber($payload->phone_num);
       if ($validate) {
           return $validate;
       }

       $is_email_updated = false;
       $current_email = Auth::user()->email_address;
       $emailAddress = strtolower($payload->email_address); //new email

       if($current_email != $emailAddress){
           $user = Worker::where('email_address', $emailAddress)->first();
           $is_email_updated = true; //true if email is updated
       }

        $profilePicture = $payload->profile_picture;
        $hasProfile = $profilePicture == 'null' || $profilePicture == ''?  false : true;
        $profilePicture = $hasProfile? $payload->profile_picture : null;

       if ($hasProfile) {
            $isBase64Profile = $payload->isBase64Profile == false || $payload->isBase64Profile == 'false'? false : true;
            if(!$isBase64Profile){
                $this->removeUploadedFile($payload->previousProfileLink, $this->googleBucket);
            }

            $image_64 = $profilePicture;
            $extension = explode('/', explode(':', substr($image_64, 0, strpos($image_64, ';')))[1])[1]; // .jpg .png
            $image = explode(',', $image_64)[1];
            $filePath = $this->createUniqueImageNameJobseeker($this->getCurrentUser()->company_id, $extension);
            $this->uploadBase64Image($image, $filePath, $this->googleBucket);

            $profilePicture = $filePath;
       }

       DB::beginTransaction();
        /*======================================================================================================== 
           preparing user data to be saved on database
       ========================================================================================================*/
       if($is_email_updated){
            $user_data = Worker::where('id', $id)->first();
            $user_data->email_address = strtolower($payload->email_address);
            $user_data->phone_num = "+1" . str_replace( array('-' , '(', ')', ' ' ), '', $payload->phone_num);
            $user_data->first_name = ucfirst($payload->first_name);
            $user_data->last_name = ucfirst($payload->last_name);
            $user_data->last_name = ucfirst($payload->last_name);
            $user_data->email_verified_at = null;
            $user_data->email_code = null;
            $user_data->mobile_code = null;
            $user_data->new_email_address = null;

            if($hasProfile){
                $user_data->profile_picture = $profilePicture;
            }    
            $userTransaction = $user_data->save();
            $userTransactionChecker = true;
           
       }else{

           $user_data = Worker::where('id', $id)->first();
           $user_data->email_address = strtolower($payload->email_address);
           $user_data->phone_num = "+1" . str_replace( array('-' , '(', ')', ' ' ), '', $payload->phone_num);
           $user_data->first_name = ucfirst($payload->first_name);
           $user_data->last_name = ucfirst($payload->last_name);
           $userTransactionChecker = $user_data->isDirty();

           if($hasProfile){
                $user_data->profile_picture = $profilePicture;
            } 
           $userTransaction = $user_data->save();
       }

        if($userTransactionChecker){
            $this->createUserAction("Updated the account information");
        }
       /*======================================================================================================== 
           send email verification if user update email
       ========================================================================================================*/
       $userTransaction = Worker::firstWhere('id', $id);
       $email_verification = false;

       if($is_email_updated){
           $verification_data = $this->generateEmailVerification($payload->email_address);
           
           $user_data = [
               'email_address'  => $payload->email_address,
               'first_name'    => $userTransaction->first_name,
               'last_name'     => $userTransaction->last_name,
               'code'          => $verification_data->code,
           ];
           $email_verification = $this->sendEmailVerification($payload->email_address, $user_data);
       }
      
       if ( !$userTransaction )
       {
           DB::rollBack();
           return response()->json(['error' => 'Server error.']);
       } else {
           DB::commit();
           if($email_verification){
               return response()->json(['success' => 'Data updated successfully. Please verify your updated email.'])->setStatusCode(201);
           }else{
               return response()->json(['success' => 'Data updated successfully'])->setStatusCode(201);
           }
       }
   }

   public function generateEmailVerification($email_address)
    {
        $verification_data = array (
            'company_id' => $this->getCurrentUser()->company_id,
            'user_id' => Auth::user()->id,
            'email_address' => $email_address,
            'type' => 'Company Email Update',
            'code' => hash('sha256', $plainTextToken = Str::random(80)),
        );
        return EmailVerification::create($verification_data);
    }

    public function sendEmailVerification($email_address, $user_data)
    {
        return ProcessSendEmailUpdateVerification::dispatch($email_address, $user_data)->onConnection('jobs_emails')->onQueue('sendemail');
    }


    public function verifyUpdatedEmailAddress($payload)
    {
        $rules = array(
            'email_address' => 'required|unique:conx_users,email_address,' . $this->userData->id . '|max:191',
        );
        $validate = $this->validateRequest($payload, $rules);
        if ($validate) {
            return $validate;
        }

        $newlyGenaratedCode = strtoupper($this->get_rand_alphanumeric());

        $userDataForEmail = [
            'email_address' => $this->userData->email_address,
            'first_name' => $this->userData->first_name,
            'last_name' => $this->userData->last_name,
            'code' => $newlyGenaratedCode,
        ];

        $newEmailAddress = strtolower($payload->email_address);

        $emailTranscation = $this->sendEmailVerificationCode($newEmailAddress, $userDataForEmail);

        $savedCodeTransaction = $this->updateAccount($this->userData->id, ['email_code' => $newlyGenaratedCode]);

        if ($emailTranscation && $savedCodeTransaction) {
            return response()->json(['success' => 'We have sent a verification code to your updated email address. Please check your inbox or spam folder to verify it.']);
        } else {
            return response()->json(['errors' => 'Something went wrong while sending verification code. Please try again later']);
        }
    }

    public function sendEmailVerificationCode($email_address, $user_data)
    {
        return ProcessEmailVerificationCode::dispatch($email_address, $user_data)->onConnection('jobs_emails')->onQueue('sendemail');
    }

    public function verifyUpdatedMobile($payload)
    {
        //Validate phone number
        $rules = array(
            'phone_number' => 'required',
        );
        $validate = $this->validateRequest($payload, $rules);
        if ($validate) {
            return $validate;
        }

        $validate = $this->validatePhoneNumber($payload->phone_number);
        if ($validate) {
            return $validate;
        }

        $recevierNumber = "+1" . str_replace(array('-', '(', ')', ' '), '', $payload->phone_number);
        $newlyGenaratedCode = strtoupper($this->generateRandomSixDigitCode());
        $message = '[ConX] Verification Code: ' . $newlyGenaratedCode;

        $sendSMSTransaction = $this->twilio->sendSMS($recevierNumber, $message);
        $savedCodeTransaction = $this->updateAccount($this->userData->id, ['mobile_code' => $newlyGenaratedCode]);

        if ($sendSMSTransaction && $savedCodeTransaction) {
            return response()->json(['success' => 'We have sent a verification code to your updated mobile number. Please check your inbox or spam folder to verify it.']);
        } else {
            return response()->json(['errors' => 'Something went wrong while sending verification code. Please try again later']);
        }
    }

    public function verificationNewMobileAndEmaillAddress($payload)
    {
        $rules = array(
            'emailVerificationCode' => 'required',
            'email_address' => 'required',
        );
        $validate = $this->validateRequest($payload, $rules);
        if ($validate) {
            return $validate;
        }

        $inputtedMobileCode = $payload->mobileVerificationCode;
        $inputteEmailCode = $payload->emailVerificationCode;

        $mobileCodeValidation = $inputtedMobileCode ? false : true;
        $emailCodeValidation = false;

        if ($inputtedMobileCode) {
            $mobileCodeValidation = Worker::where('mobile_code', $inputtedMobileCode)->first();

            if (!$mobileCodeValidation) {
                return response()->json(['errors' => 'The inputted mobile verification code is invalid.']);
            }
        }

        $emailCodeValidation = Worker::where('email_code', $inputteEmailCode)->first();

        if (!$emailCodeValidation) {
            return response()->json(['errors' => 'The inputted email verification code is invalid.']);
        }

        $newEmailAddress = strtolower($payload->email_address);

        $userData = array(
            'email_address' => $newEmailAddress,
            'phone_num' => "+1" . str_replace(array('-', '(', ')', ' '), '', $payload->phone_num),
            'first_name' => $payload->first_name,
            'last_name' => $payload->last_name,
            'email_code' => '',
            'email_verified_at' => now(),
        );

        if ($inputtedMobileCode) {
            $userData['mobile_code'] = '';
        }

        $updateUserTransaction = $this->updateAccount($this->userData->id, $userData);

        if ($updateUserTransaction) {
            return response()->json(['success' => 'Account Successfully Updated!']);
        } else {
            return response()->json(['errors' => 'Something went wrong while proccessing the verification code. Please try again later']);
        }

    }

    public function sendMobile($payload)
    {
        //Validate phone number
        $rules = array(
            'phone_num' => 'required',
        );
        $validate = $this->validateRequest($payload, $rules);
        if ($validate) {
            return $validate;
        }

        $validate = $this->validatePhoneNumber($payload->phone_num);
        if ($validate) {
            return $validate;
        }

        $recevierNumber = "+1" . str_replace(array('-', '(', ')', ' '), '', $payload->phone_num);
        $newlyGenaratedCode = strtoupper($this->generateRandomSixDigitCode());
        $message = '[ConX] Verification Code: ' . $newlyGenaratedCode;
        
        $sendSMSTransaction = $this->twilio->sendSMS($recevierNumber, $message);
        $savedCodeTransaction = $this->updateAccount($this->userData->id, ['mobile_code' => $newlyGenaratedCode]);

        if ($sendSMSTransaction && $savedCodeTransaction) {
            return response()->json(['success' => 'Mobile verification code successfully sent.']);
        } else {
            return response()->json(['errors' => 'Something went wrong while sending verification code. Please try again later']);
        }
    }

    public function verificationOfMobileCode($payload)
    {
        $rules = array(
            'code' => 'required',
        );
        $validate = $this->validateRequest($payload, $rules);
        if ($validate) {
            return $validate;
        }

        $user_id =  $this->userData->id;
        $user = Worker::where('id', $user_id)->first();

        /* Datas for email notif */
        $email_address = $user->email_address;
        $user_data = [
                'email_address' => $user->email_address,
                'first_name' =>  $user->first_name,
                'last_name'=> $user->last_name,
            ];

        if($user->mobile_code == $payload->code){
            ProcessMobileUpdateNotificationEmail::dispatch($email_address, $user_data)->onConnection('jobs_emails')->onQueue('sendemail');
            return response()->json(['success'=> 'Execute Update']);
        }else{
            return response()->json(['errors'=> 'You have inputted an invalid code.']);
        }
    }

    public function verifyNewMobileAndEmaillAddress($payload)
    {
        $userId = $this->userData->id;

        $rules = array(
            'email_address' => 'required|unique:conx_users,email_address,' . $userId . '|max:191',
            'phone_number' => 'required',
        );
        $validate = $this->validateRequest($payload, $rules);
        if ($validate) {
            return $validate;
        }

        $recevierNumber = "+1" . str_replace(array('-', '(', ')', ' '), '', $payload->phone_number);

        $validate = $this->validatePhoneNumber($recevierNumber);
        if ($validate) {
            return $validate;
        }

        $emailGenaratedCode = strtoupper($this->get_rand_alphanumeric());
        $mobileGenaratedCode = strtoupper($this->get_rand_alphanumeric());
        $smsMessage = '[ConX] Verification Code: ' . $mobileGenaratedCode;

        $userDataForEmail = [
            'email_address' => $this->userData->email_address,
            'first_name' => $this->userData->first_name,
            'last_name' => $this->userData->last_name,
            'code' => $emailGenaratedCode,
        ];

        $emailTranscation = $this->sendEmailVerificationCode($payload->email_address, $userDataForEmail);
        $sendSMSTransaction = $this->twilio->sendSMS($recevierNumber, $smsMessage);
        $savedCodeTransaction = $this->updateAccount($this->userData->id, ['email_code' => $emailGenaratedCode, 'mobile_code' => $mobileGenaratedCode]);

        if ($emailTranscation && $sendSMSTransaction && $savedCodeTransaction) {
            return response()->json(['success' => 'We have sent a verification code to your updated email address and mobile number. Please check your inbox or spam folder to verify it.']);
        } else {
            return response()->json(['errors' => 'Something went wrong while sending verification code. Please try again later']);
        }
    }

}