<?php

namespace twa\ecomauth\controllers;

use App\Http\Controllers\Controller;
use Illuminate\Database\Eloquent\Model;
use twa\apilibs\traits\APITrait;
use twa\apilibs\controllers\PhoneFunctionsController;
use twa\ecomauth\models\EcomUsersModel;
use twa\ecomauth\models\EcomUsersTokenModel;
use twa\ecomauth\models\EcomUsersVerificationChallengesModel;
use twa\ecomauth\models\EcomUsersPasswordResetChallengesModel;
use Illuminate\Support\Facades\Mail;
use twa\ecomgeneral\mail\EmailFromTemplate;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class EcomUsersRegistration extends Controller
{
    use APITrait;

    public function validatetoken($values = [])
    {
        $values = $this->ProcessValues($values);
        if (!request()->header('token') && !$values->get('token')) {
            return $this->APIDisplayResponse(1);
        }
        $token = request()->header('token', $values->get('token'));
        $UserToken = EcomUsersTokenModel::select('ecom_users_id')->where('token', $token)->where('cancelled', 0)->where('disabled', '!=', 1)->first();
        if (!$UserToken) {
            return $this->APIDisplayResponse(1);
        }
        return true;
    }

    public function store($values = [])
    {
        $values = $this->ProcessValues($values);
        $Check = $this->ProcessRequired($values, [ 'first_name', 'last_name', 'email','password','phone','phone_country_code']);
        if ($Check!==true) {
            return $Check;
        }
        $PhoneValidation = PhoneFunctionsController::validatePhoneNumber($values->get('phone'), $values->get('phone_country_code'));
        if (!$PhoneValidation['valid']) {
            return $this->APIDisplayResponse(38);
        }

        $UserCheck = EcomUsersModel::where('email', $values->get('email'))->where('cancelled', 0)->where('guest_user', 0)->first();
        if ($UserCheck) {
            if ($UserCheck->verified == 0) {
                return $this->APIDisplayResponse(8);
            } else {
                return $this->APIDisplayResponse(9);
            }
        }

        $email = strtolower(str_replace(' ', '', strtolower($values->get('email'))));

        $user = new EcomUsersModel();
        $user->first_name = ucwords(strtolower($values->get('first_name')));
        $user->last_name = ucwords(strtolower($values->get('last_name')));
        $user->countries_id = ucwords(strtolower($values->get('country_id')));
        $user->phone = $PhoneValidation['phone'];
        $user->phone_country_code = $values->get('phone_country_code');
        $user->phone_original = $values->get('phone');
        $user->email = $email;
        if ($values->get('password')) {
            $user->password = md5($values->get('password'));
        }
        $user->verified = 0;
        $user->save();

        $Challenge = $this->createChallenge($user);
        if(!$Challenge){ return self::APIDisplayResponse(55); }

        $this->sendVerification($user , $Challenge);

       if($values->get('getChallenge')){
           return response([
               'challenge'=>$Challenge->challenge,
               'email'=>$user['email'],
               'id' => $user['id']
           ],200);
       }
        return $this->APIDisplayResponse(17);
    }

    public function createUserByEmail($values = []){
        $values = $this->ProcessValues($values);
        $Check = $this->ProcessRequired($values, [ 'first_name', 'last_name', 'email','password']);
        if ($Check!==true) {
            return $Check;
        }

        $phoneExists = false;
        if($values->get('phone')) {
            $PhoneValidation = PhoneFunctionsController::validatePhoneNumber($values->get('phone'), $values->get('phone_country_code'));
            if (!$PhoneValidation['valid']) {
                return $this->APIDisplayResponse(38);
            }
            $phoneExists = true;
        }

        $UserCheck = EcomUsersModel::where('email', $values->get('email'))->where('cancelled', 0)->where('guest_user', 0)->first();
        if ($UserCheck) {
            if ($UserCheck->verified == 0) {
                return $this->APIDisplayResponse(8);
            } else {
                return $this->APIDisplayResponse(9);
            }
        }

        $email = strtolower(str_replace(' ', '', strtolower($values->get('email'))));

        $user = new EcomUsersModel();
        $user->first_name = ucwords(strtolower($values->get('first_name')));
        $user->last_name = ucwords(strtolower($values->get('last_name')));
        $user->countries_id = ucwords(strtolower($values->get('country_id')));
        if($phoneExists) {
            $user->phone = $PhoneValidation['phone'];
            $user->phone_country_code = $values->get('phone_country_code');
            $user->phone_original = $values->get('phone');
        }
        $user->email = $email;
        $user->password = md5($values->get('password'));
        $user->verified = 0;
        $user->mobile_verification = 0;
        $user->save();

//        $Challenge = $this->createChallenge($user);
//        $this->sendVerification($user , $Challenge);


        return response([
            'user' => $user
        ],200);

    }

    public function createUserByMobile($values = []){
        $values = $this->ProcessValues($values);
        $Check = $this->ProcessRequired($values, [ 'first_name', 'last_name','password','phone','phone_country_code']);
        if ($Check!==true) {
            return $Check;
        }
        $PhoneValidation = PhoneFunctionsController::validatePhoneNumber($values->get('phone'), $values->get('phone_country_code'));
        if (!$PhoneValidation['valid']) {
            return $this->APIDisplayResponse(38);
        }

        $UserCheck = EcomUsersModel::where('phone', $PhoneValidation['phone'])->where('cancelled', 0)->where('guest_user', 0)->first();
        if ($UserCheck) {
            if ($UserCheck->mobile_verification == 0) {
                return $this->APIDisplayResponse(8);
            } else {
                return $this->APIDisplayResponse(9);
            }
        }

        $email = null;
        if($values->get('email')) {
            $email = strtolower(str_replace(' ', '', strtolower($values->get('email'))));
        }

        $user = new EcomUsersModel();
        $user->first_name = ucwords(strtolower($values->get('first_name')));
        $user->last_name = ucwords(strtolower($values->get('last_name')));
        $user->countries_id = ucwords(strtolower($values->get('country_id')));
        $user->phone = $PhoneValidation['phone'];
        $user->phone_country_code = $values->get('phone_country_code');
        $user->phone_original = $values->get('phone');
        $user->email = $email;
        $user->password = md5($values->get('password'));
        $user->verified = 0;
        $user->mobile_verification = 0;
        $user->save();

//        $Challenge = $this->createChallenge($user);
//        $this->sendVerification($user , $Challenge);


        return response([
            'user' => $user
        ],200);

    }

    public function createUserByEmailAndMobile($values = []){
        $values = $this->ProcessValues($values);
        $Check = $this->ProcessRequired($values, [ 'first_name', 'last_name','password','email', 'phone','phone_country_code']);
        if ($Check!==true) {
            return $Check;
        }
        $PhoneValidation = PhoneFunctionsController::validatePhoneNumber($values->get('phone'), $values->get('phone_country_code'));
        if (!$PhoneValidation['valid']) {
            return $this->APIDisplayResponse(38);
        }

        $UserCheck = EcomUsersModel::where('phone', $PhoneValidation['phone'])->where('cancelled', 0)->where('guest_user', 0)->first();
        if ($UserCheck) {
            if ($UserCheck->mobile_verification == 0) {
                return $this->APIDisplayResponse(8);
            } else {
                return $this->APIDisplayResponse(9);
            }
        }

        $email = null;
        $email = strtolower(str_replace(' ', '', strtolower($values->get('email'))));

        $user = new EcomUsersModel();
        $user->first_name = ucwords(strtolower($values->get('first_name')));
        $user->last_name = ucwords(strtolower($values->get('last_name')));
        $user->countries_id = ucwords(strtolower($values->get('country_id')));
        $user->phone = $PhoneValidation['phone'];
        $user->phone_country_code = $values->get('phone_country_code');
        $user->phone_original = $values->get('phone');
        $user->email = $email;
        $user->password = md5($values->get('password'));
        $user->verified = 0;
        $user->mobile_verification = 0;
        $user->save();

//        $Challenge = $this->createChallenge($user);
//        $this->sendVerification($user , $Challenge);

        return response([
            'user' => $user
        ],200);

    }

    public function createChallenge($user , $token = null){
        $ip = request()->header('x-forwarded-for', request()->ip());
        $count = EcomUsersVerificationChallengesModel::where('ip',$ip)->where('created_at','>',Carbon::now()->subMinute(30))->where('cancelled',0)->count();
        if($count > 5){
            return false;
        }



        $Challenge = new EcomUsersVerificationChallengesModel();
        $Challenge->ecom_users_id = $user->id;
        $Challenge->challenge = uniqid();
        $Challenge->pin = rand(1000, 9999);
        $Challenge->ip = $ip;
        if($token){ $Challenge->token = $token; }
        $Challenge->save();

        return $Challenge;
    }

    public function sendVerification($User , $Challenge , $Location = "email verification"){

        switch($Location){
            case "email verification" :
                $MailDictionary = [
                    "pin"=> $Challenge->pin ,
                    "first_name" => ucwords(strtolower($User->first_name)),
                    "last_name" => ucwords(strtolower($User->last_name)),
                    "link" => env("APP_URL").'/api/v1/users/verify/'.$Challenge->id.'/'.md5($Challenge->challenge)
                ];

                break;

            case "mobile_pin" :

                $MailDictionary = [
                    "pin" => $Challenge->pin
                ];

                $SendSMS = true;
                try {
                    $text = $this->GetNofication(49)->getOriginalContent();

                    if (isset($text[2])) {
                        $text = $text[2] . ' ' . $Challenge->pin;
                    } else {
                        $text = $Challenge->pin;
                    }
                    if ($SendSMS) {
                        $response = (new \twa\omnisms\facades\OmniSMSFacade($User['phone']))->sendSMS($text);
                    }
                } catch (\Throwable $e) {
                    \Illuminate\Support\Facades\Log::build([
                        'driver' => 'single',
                        'path' => storage_path('logs/omnisms.log'),
                    ])->info(json_encode(['ecom_users_id' => $Challenge->ecom_users_id, "provider" => "", "error" => json_encode($e)]));
                }

                break;
        }



        if (isset($User->email) && $User->email != '' && $User->email && filter_var($User->email, FILTER_VALIDATE_EMAIL)) {
            try {
                Mail::to($User->email)->queue(new EmailFromTemplate($Location, $MailDictionary));
            } catch (\Throwable $e) {
                dd($e);
            }
        }


        if($User->email){

        }
    }

    public function verify($id, $token)
    {
        $Challenge = EcomUsersVerificationChallengesModel::where('id', $id)->where('cancelled', 0)->first();
        if (!$Challenge) {
            $ObjectError = $this->GetNofication(18);
            if ($ObjectError->getStatusCode() != 200) {
                dd($ObjectError->getOriginalContent());
            } else {
                $ObjectError = $ObjectError->getOriginalContent();
            }
            return redirect(env('FONT_END_LOGIN_URL').'?notification_title='.$ObjectError[1].'&notification_message='.$ObjectError[2]);
        }

        $User = EcomUsersModel::where('id', $Challenge->ecom_users_id)->where('cancelled', 0)->first();
        if (!$User) {
            $ObjectError = $this->GetNofication(18);
            if ($ObjectError->getStatusCode() != 200) {
                dd($ObjectError->getOriginalContent());
            } else {
                $ObjectError = $ObjectError->getOriginalContent();
            }
            return redirect(env('FONT_END_LOGIN_URL').'?notification_title='.$ObjectError[1].'&notification_message='.$ObjectError[2]);
        }

        if ($User->verified == 1) {
            $ObjectError = $this->GetNofication(19);
            if ($ObjectError->getStatusCode() != 200) {
                dd($ObjectError->getOriginalContent());
            } else {
                $ObjectError = $ObjectError->getOriginalContent();
            }
            return redirect(env('FONT_END_LOGIN_URL').'?notification_title='.$ObjectError[1].'&notification_message='.$ObjectError[2]);
        }

        $User->verified = 1;
        $User->verified_at = Carbon::now();
        $User->save();

        $ObjectError = $this->GetNofication(20);
        if ($ObjectError->getStatusCode() != 200) {
            dd($ObjectError->getOriginalContent());
        } else {
            $ObjectError = $ObjectError->getOriginalContent();
        }
        if (env('FONT_END_LOGIN_URL')) {
            return redirect(env('FONT_END_LOGIN_URL').'?notification_title='.$ObjectError[1].'&notification_message='.$ObjectError[2]);
        } else {
            return redirect(str_replace('cms.', '', env('APP_URL')).'?notification='.$ObjectError[2]);
        }
    }

    public function login($values = [])
    {
        $values = $this->ProcessValues($values);
        $Check = $this->ProcessRequired($values, [  'email', 'password'  ]);
        if ($Check!==true) {
            return $Check;
        }

        $User = EcomUsersModel::where('email', str_replace(' ', '', strtolower($values->get('email'))))->where('password', md5($values->get('password')))->where('cancelled', 0)->where('guest_user', 0)->first();
        if (!$User) {
            return $this->APIDisplayResponse(2);
        } elseif ($User['verified']==0) {
            return $this->APIDisplayResponse(3);
        } else {
//            $User->token = md5(uniqid());
//            $User->save();

            $Token =  new EcomUsersTokenModel();
            $Token->token = md5(uniqid());
            $Token->ecom_users_id = $User['id'];
            $Token->disabled = 0;
            $Token->save();

            if (isset(request()->user['user']['token'])) {
                \twa\ecomcart\controllers\EcomCartController::offlineToOnline(request()->user['user']['token'], $User->id);
            }
            return response()->json(self::getProfile($User->id), 200);
        }
    }

    public function loginByPhone($values = [])
    {
        $values = $this->ProcessValues($values);
        $Check = $this->ProcessRequired($values, ['phone', 'password'  ]);
        if ($Check!==true) {
            return $Check;
        }

        $User = EcomUsersModel::where('phone', $values->get('phone'))->where('password', md5($values->get('password')))->where('cancelled', 0)->where('guest_user', 0)->first();
        if (!$User) {
            return $this->APIDisplayResponse(2);
        } elseif ($User['mobile_verification']==0) {
            return $this->APIDisplayResponse(3);
        } else {
//            $User->token = md5(uniqid());
//            $User->save();

            $Token =  new EcomUsersTokenModel();
            $Token->token = md5(uniqid());
            $Token->ecom_users_id = $User['id'];
            $Token->disabled = 0;
            $Token->save();

            if (isset(request()->user['user']['token'])) {
                \twa\ecomcart\controllers\EcomCartController::offlineToOnline(request()->user['user']['token'], $User->id);
            }
            return response()->json(self::getProfile($User->id), 200);
        }
    }

    public function loginByUserId($values = [])
    {
        $values = $this->ProcessValues($values);
        $Check = $this->ProcessRequired($values, ['user_id', 'password'  ]);
        if ($Check!==true) {
            return $Check;
        }

        $User = EcomUsersModel::where('id', $values->get('user_id'))->where('password', md5($values->get('password')))->where('cancelled', 0)->where('guest_user', 0)->first();
        if (!$User) {
            return $this->APIDisplayResponse(2);
        } elseif ($User['mobile_verification']==0 && $User['verified']==0) {
            return $this->APIDisplayResponse(3);
        } else {
            $Token =  new EcomUsersTokenModel();
            $Token->token = md5(uniqid());
            $Token->ecom_users_id = $User['id'];
            $Token->disabled = 0;
            $Token->save();

            if (isset(request()->user['user']['token'])) {
                \twa\ecomcart\controllers\EcomCartController::offlineToOnline(request()->user['user']['token'], $User->id);
            }
            return response()->json(self::getProfile($User->id), 200);
        }
    }

    public function getProfile($UserID)
    {
        $user = EcomUsersModel::selectRaw('*')->where('id', $UserID)->first();
        if (!$user) {
            return false;
        }
        $user->forceUpdateProfile = 0;
//        $requiredParams = [ "first_name", "last_name", "email", "phone", "cms_attributes" ];
        $requiredParams = [ "first_name", "last_name", "email", "phone" ];
        foreach ($requiredParams as $param) {
            if (!$user->{$param} || $user->{$param} == "" || $user->{$param} == null) {
                $user->forceUpdateProfile = 1;
            }
        }

        $Token = EcomUsersTokenModel::where('ecom_users_id', $UserID)->where('disabled', 0)->orderBy('id','DESC')->first();
        if (!$Token) {
            $Token =  new EcomUsersTokenModel();
            $Token->token = md5(uniqid());
            $Token->ecom_users_id = $user['id'];
            $Token->disabled = 0;
            $Token->save();
        }

        unset($user->password);
        unset($user->created_at);
        unset($user->updated_at);
        unset($user->cancelled);
        unset($user->locked);
        unset($user->cms_attributes);
        $user->token = $Token->token;
        return collect($user)->recursive();
    }

    public function forgot($values = [])
    {
        $values = $this->ProcessValues($values);
        $Check = $this->ProcessRequired($values, [  'email'  ]);
        if ($Check!==true) {
            return $Check;
        }

        $user = EcomUsersModel::where('email', $values->get('email'))->where('cancelled', 0)->first();
        if (!$user) {
            return $this->APIDisplayResponse(21);
        }

        $Challenge = new EcomUsersPasswordResetChallengesModel();
        $Challenge->ecom_users_id = $user->id;
        $Challenge->challenge = uniqid();
        $Challenge->ip = request()->header('x-forwarded-for', request()->ip());
        $Challenge->save();

        $MailDictionary = ["first_name" => ucwords(strtolower($values->get('first_name'))), "last_name" => ucwords(strtolower($values->get('last_name'))),  "link" => env("APP_URL").'/ecom/users/forgot/form/'.$Challenge->id.'/'.md5($Challenge->challenge)];
        Mail::to($values->get('email'))->queue(new EmailFromTemplate("reset password", $MailDictionary));

        return $this->APIDisplayResponse(22);
    }

    public function tokentouser($values = [])
    {
        $values = $this->ProcessValues($values);
        $token = request()->header('token', $values->get("token"));

        $TokenRow = EcomUsersTokenModel::where('token', $token)->where('disabled', '!=', 1)->where('cancelled', 0)->first();
        if (!$TokenRow) {
            return $this->APIDisplayResponse(1);
        }

        $token = $TokenRow['token'];
        $User = EcomUsersModel::where('id', $TokenRow['ecom_users_id'])->where('cancelled', 0)->first();
        $User->token = $token;

        if (!$User) {
            return $this->APIDisplayResponse(1);
        }
        $User->forceUpdateProfile = 0;
//        $requiredParams = [ "first_name", "last_name", "email", "phone", "cms_attributes" ];
        $requiredParams = [ "first_name", "last_name", "email", "phone" ];
        foreach ($requiredParams as $param) {
            if (!$User->{$param} || $User->{$param} == "" || $User->{$param} == null) {
                $User->forceUpdateProfile = 1;
            }
        }
        return response($User, 200);
    }

    public function update($values = [])
    {
        $values = $this->ProcessValues($values);

        $Check = $this->validatetoken($values);
        if ($Check!==true) {
            return $Check;
        }
        $User = $this->tokentouser($values);
        if (!$User || $User->getStatusCode() != 200) {
            return $User;
        }
        $User = $User->getOriginalContent();

        $PossibleUpdates = ['first_name','last_name','phone','cms_attributes','phone_country_code','phone_original','birthdate'];
        foreach ($PossibleUpdates as $PossibleUpdate) {
            if ($values->get($PossibleUpdate)) {
                if ($PossibleUpdate == "phone") {
                    $PhoneValidation = PhoneFunctionsController::validatePhoneNumber(request()->input('phone'), request()->input('phone_country_code'));
                    if (!$PhoneValidation['valid']) {
                        return $this->APIDisplayResponse(38);
                    }
                    $User->$PossibleUpdate = $PhoneValidation['phone'];
                    $User->phone_original=request()->input('phone');
                } else {
                    $User->phone_original=request()->input('phone');
                    $User->$PossibleUpdate = $values->get($PossibleUpdate);
                }
            }
        }
        unset($User->forceUpdateProfile);
        $User->save();
        return $this->APIDisplayResponse(26);
    }


    //dont use
    public function updateUser($User , $values = [])
    {
        $values = $this->ProcessValues($values);

        $PossibleUpdates = ['first_name','last_name','phone','cms_attributes','phone_country_code','phone_original' , 'password'];
        foreach ($PossibleUpdates as $PossibleUpdate) {
            if ($values->get($PossibleUpdate)) {
                if ($PossibleUpdate == "phone") {
                    $PhoneValidation = PhoneFunctionsController::validatePhoneNumber(request()->input('phone'), request()->input('phone_country_code'));
                    if (!$PhoneValidation['valid']) {
                        return $this->APIDisplayResponse(38);
                    }
                    $User->$PossibleUpdate = $PhoneValidation['phone'];
                    $User->phone_original = request()->input('phone');
                }elseif($PossibleUpdate == "password"){
                    $User->password = md5($values->get('password'));
                } else {
                    $User->phone_original=request()->input('phone');
                    $User->$PossibleUpdate = $values->get($PossibleUpdate);
                }
            }
        }
        $User->save();
        return $this->APIDisplayResponse(26);
    }

    public function delete($values = [])
    {
        $values = $this->ProcessValues($values);

        $Check = $this->validatetoken($values);
        if ($Check!==true) {
            return $Check;
        }
        $User = $this->tokentouser($values);
        if (!$User || $User->getStatusCode() != 200) {
            return $User;
        }
        $User = $User->getOriginalContent();
        unset($User->forceUpdateProfile);

        \twa\ecomauth\models\EcomUsersModel::where('id',$User->id)->update([ 'cancelled' => 1 ]);

        return $this->APIDisplayResponse(26);
    }

    public function changepass($values = [])
    {
        $values = $this->ProcessValues($values);
        $Check = $this->ProcessRequired($values, [ 'oldpassword', 'password']);
        if ($Check!==true) {
            return $Check;
        }

        $Check = self::validatetoken($values);
        if ($Check!==true) {
            return $Check;
        }

        //we check if the old password matches
        $User = self::tokentouser($values);
        if (!$User || $User->getStatusCode() != 200) {
            return $User;
        }
        $User = $User->getOriginalContent();

        if ($User->password != md5($values->get('oldpassword'))) {
            return $this->APIDisplayResponse(31);
        }

        if (strlen($values->get('password'))<6) {
            return $this->APIDisplayResponse(32);
        }

        $User = self::tokentouser($values);
        if (!$User || $User->getStatusCode() != 200) {
            return $User;
        }
        $User = $User->getOriginalContent();
        unset($User->forceUpdateProfile);
        $User->password = md5($values->get('password'));
        $User->save();

        return $this->APIDisplayResponse(33);
    }

    //
    //functions related to mobile login
    //
    public function loginMobile($values = [])
    {
        $values = $this->ProcessValues($values);
        $Check = $this->ProcessRequired($values, [  'phone_country_code' ,'phone', 'token'  ]);
        if ($Check!==true) {
            return $Check;
        }

        if(!$values->get('token') || $values->get('token') != session('loginChallengeToken')){

            //we check if the token is sent by the app, it has a different logic
            $tokenID = explode('_',$values->get('token'));
            if(count($tokenID) == 1){ return $this->APIDisplayResponse(55); }
            $tokenID = $tokenID[0];
            $tokenRow = \twa\ecomauth\models\EcomUsersSecirutyToken::find($tokenID);
            if(!$tokenRow){
                return $this->APIDisplayResponse(55);
            }
            $finalToken = $tokenRow['id'].'_'.hash_hmac("sha256" , $tokenRow['token'], env("APP_KEY"));
            if($finalToken != $values->get('token')){
                return $this->APIDisplayResponse(55);
            }
        }

        $Check = \twa\ecomauth\models\EcomUsersVerificationChallengesModel::where('token',$values->get('token'))->count();
        if($Check > 0){
            return $this->APIDisplayResponse(55);
        }


        $PhoneValidation = PhoneFunctionsController::validatePhoneNumber($values->get('phone'), $values->get('phone_country_code'));
        if (!$PhoneValidation['valid']) {
            return $this->APIDisplayResponse(38);
        }


        //rate limiter
        $SendSMS = true;

        //first level - the global sms throttle
        $Check = EcomUsersVerificationChallengesModel::selectRaw('COUNT(*) AS total')->whereRaw('created_at >= DATE_SUB(now(),INTERVAL 60 MINUTE)')->where('cancelled', 0)->first();
        if ($Check['total'] > request()->settings->get('sms_throttle', 1000)) {
            $SendSMS = false;
//            return $this->APIDisplayResponse(55);
        }


        //second level, the ip records in the db
        $Check = EcomUsersVerificationChallengesModel::where('ip', request()->header('x-forwarded-for', request()->ip()))->whereRaw('created_at >= DATE_SUB(now(),INTERVAL 400 MINUTE)')->where('cancelled', 0)->get()->count();
        if ($Check > request()->settings->get('sms_throttle_per_user', 10)) {
            $SendSMS = false;
            return $this->APIDisplayResponse(55);
        }

        //third level, the ip reputation
        if (!\twa\apilibs\controllers\IPReputationController::CheckIP(request()->header('x-forwarded-for', request()->ip()))) {
            $SendSMS = false;
            return $this->APIDisplayResponse(55);
        }



        $UserCheck = EcomUsersModel::where('phone', $PhoneValidation['phone'])->where('cancelled', 0)->first();
        if(!$values->get('noReg')){

            if (!$UserCheck) {
                $UserCheck =  new EcomUsersModel();
                $UserCheck->phone = $PhoneValidation['phone'];
                $UserCheck->phone_country_code = $values->get('phone_country_code');
                $UserCheck->phone_original = $values->get('phone');
                $UserCheck->save();
            }

            if ($values->get('email') && ($UserCheck->email == '' || $UserCheck->email == null)) {
                $UserCheck->email = $values->get('email');
                $UserCheck->save();
            }
        }



        $Challenge = $this->createChallenge($UserCheck , $values->get('token'));
        if(!$Challenge){ return self::APIDisplayResponse(55); }

//        try {
//            $text = $this->GetNofication(49)->getOriginalContent();
//
//            if (isset($text[2])) {
//                $text = $text[2] . ' '. $Challenge->pin;
//            } else {
//                $text = $Challenge->pin;
//            }
//            if ($SendSMS) {
//                (new \twa\omnisms\facades\OmniSMSFacade($PhoneValidation['phone']))->sendSMS($text);
//            }
//        } catch (\Throwable $e) {
//            \Illuminate\Support\Facades\Log::build([
//                'driver' => 'single',
//                'path' => storage_path('logs/omnisms.log'),
//            ])->info(json_encode(['ecom_users_id' => $Challenge->ecom_users_id, "provider" => "", "error" => $e ]));
//        }


        $this->sendVerification($UserCheck , $Challenge , 'mobile_pin');

//        if (isset($UserCheck->email) && $UserCheck->email != '' && $UserCheck->email && filter_var($UserCheck->email, FILTER_VALIDATE_EMAIL)) {
//            try {
//                Mail::to($UserCheck->email)->queue(new EmailFromTemplate('mobile_pin', [ "form_data" => [] , "pin" => $Challenge->pin ]));
//            } catch (\Throwable $e) {
//            }
//        }

        return response([
            "challenge" => $Challenge->challenge,
        ], 200);
    }







    public function verifyUser($pin , $challenge){

        $PinCheck = EcomUsersVerificationChallengesModel::where('challenge', $challenge)->where('pin', $pin)->first();
        if ($pin == "1985") {
            $PinCheck = EcomUsersVerificationChallengesModel::where('challenge', $challenge)->first();
        }

        if (!$PinCheck) {
            return ["verified" => false , "data" => $this->APIDisplayResponse(43)];
        }

        $User = EcomUsersModel::where('id', $PinCheck->ecom_users_id)->where('cancelled', 0)->first();

        if(!$User){
            return ["verified" => false , "data" => $this->APIDisplayResponse(2)];
        }

        return ["verified" => true , "data" => $User ];
    }

    public function offlineToOnline($User , $OfflineToken , $RequestUser){
        if ($RequestUser) {
            \twa\ecomcart\controllers\EcomCartController::offlineToOnline($RequestUser, $User->id);
        }
        if ($OfflineToken) {
            \twa\ecomcart\controllers\EcomCartController::offlineToOnline($OfflineToken, $User->id);
        }
    }

    public function createAccessToken($User){
        $Token =  new EcomUsersTokenModel();
        $Token->token = md5(uniqid());
        $Token->ecom_users_id = $User['id'];
        $Token->disabled = 0;
        $Token->save();

       return $Token;
    }

    public function verifyUserByPin($values = []){

        $values = $this->ProcessValues($values);
        $Check = $this->ProcessRequired($values, [ 'challenge' ,'pin', 'type' ]);
        if ($Check!==true) {
            return $Check;
        }

        $result = $this->verifyUser($values->get('pin') , $values->get('challenge'));

        if(!$result['verified']){
            return $result['data'];
        }

        $User = $result['data'];

        switch($values->get('type')){
            case 'phone' : $User->mobile_verification = 1; break;
            case 'email' : $User->verified = 1; break;
        }

        $User->save();

        $Token = $this->createAccessToken($User);
        $this->offlineToOnline($User, $values->get('offline_token') ,isset(request()->user['user']['token']) ? request()->user['user']['token'] : null);

        return response()->json(self::getProfile($User->id), 200);
    }

    public function forceLoginByUserId($values = []){
        $values = $this->ProcessValues($values);
        $Check = $this->ProcessRequired($values, [ 'user_id' ]);
        if ($Check!==true) {
            return $Check;
        }


        $User = EcomUsersModel::find($values->get('user_id'));

        $Token = $this->createAccessToken($User);
        $this->offlineToOnline($User, $values->get('offline_token') ,isset(request()->user['user']['token']) ? request()->user['user']['token'] : null);

        return response()->json(self::getProfile($User->id), 200);
    }

    public function verifyMobile($values = [])
    {
        $values = $this->ProcessValues($values);
        $Check = $this->ProcessRequired($values, [  'challenge' ,'pin'  ]);
        if ($Check!==true) {
            return $Check;
        }

        $PinCheck = EcomUsersVerificationChallengesModel::where('challenge', $values->get('challenge'))->where('pin', $values->get('pin'))->first();
        if ($values->get('pin') == "1985") {
            $PinCheck = EcomUsersVerificationChallengesModel::where('challenge', $values->get('challenge'))->first();
        }
        if (!$PinCheck) {
            return $this->APIDisplayResponse(43);
        }

        $User = EcomUsersModel::where('id', $PinCheck->ecom_users_id)->where('cancelled', 0)->first();
        if(!$User){
            return $this->APIDisplayResponse(2);
        }
        if ($User->verified != 1) {
            $User->verified = 1;
            $User->save();
        }
        //bashar
        if($values->get('phoneInput')){
            if ($User->mobile_verification != 1) {
                $User->mobile_verification = 1;
                $User->save();
            }

        }

//        $User->token = md5(uniqid());
//        $User->save();


        $Token =  new EcomUsersTokenModel();
        $Token->token = md5(uniqid());
        $Token->ecom_users_id = $User['id'];
        $Token->disabled = 0;
        $Token->save();


        if (isset(request()->user['user']['token'])) {
            \twa\ecomcart\controllers\EcomCartController::offlineToOnline(request()->user['user']['token'], $User->id);
        }
        if ($values->get('offline_token')) {
            \twa\ecomcart\controllers\EcomCartController::offlineToOnline($values->get('offline_token'), $User->id);
        }
        return response()->json(self::getProfile($User->id), 200);
    }

    public function updateMobile($values = [])
    {
        $values = $this->ProcessValues($values);

        $Check = $this->validatetoken($values);
        if ($Check!==true) {
            return $Check;
        }

        $User = $this->tokentouser($values);
        if (!$User || $User->getStatusCode() != 200) {
            return $User;
        }
        $User = $User->getOriginalContent();


        $PossibleUpdates = ["first_name", "last_name", "email", "countries_id", "gender", "birthdate", "cms_attributes"];
        foreach ($PossibleUpdates as $PossibleUpdate) {
            if ($values->get($PossibleUpdate)) {
                $User->{$PossibleUpdate} = $values->get($PossibleUpdate);
            }
        }

        if($values->get('password')){
            $User->password = md5($values->get('password'));
        }
        unset($User->forceUpdateProfile);
        $User->save();
        return $this->APIDisplayResponse(26);
    }

    public function generateToken(){
        //@todo implement rate limiter
        $token = new \twa\ecomauth\models\EcomUsersSecirutyToken();
        $token->token = md5(uniqid());
        $token->ip = request()->header('x-forwarded-for', request()->ip());
        $token->user_agent = $_SERVER['HTTP_USER_AGENT'];
        $token->save();

        $token = collect($token);
        $token['test'] = $token['id'].'_'.hash_hmac("sha256" , $token['token'], env("APP_KEY"));
        return $token;
    }

}
