<?php
require_once '_master/apiHandler.php'; // الكلاس الأساسي
class pageClass extends apiHandler
{
    public function __construct() {
        parent::__construct(); 
        $this->checkERPAccess();
        // $this->checkTokenClient();
    }

    function add() {
        try{

            if($this->optSend == 1){
                $ruleemail =  'required|email|min:1|max:100';
            }else{
                $rulemobiloe = 'email|min:1|max:100';
            }
            $allowed = ['name','mobile','email','password','password_confirmation','private_key','affiliate_mobile','branch_id','governorate_id','city_id','address','address_type','latitude','longitude'];
            $fields = [
                'name' => [
                    'rules' => 'required|text|min:1|max:200',
                    'type'  => 'string',
                ],
                'mobile' => [
                    'rules' => 'required|numeric|min:8|max:11',
                    'type'  => 'integer',
                ],
                'email' => [
                    'rules' => $rulemobiloe,
                    'type'  => 'email',
                ],
                'password' => [
                    'rules' => 'required|min:8|password:~^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[@$!%*?&\#])[A-Za-z0-9@$!%*?&\#]{8,}$~|confirmed',
                    'type'  => 'password',
                ],
                'password_confirmation' => [
                    'rules' => 'required',
                    'type'  => 'password',
                ],
                'private_key' => [
                    'rules' => 'text|min:1|max:200',
                    'type'  => 'string',
                ],
                'affiliate_mobile' => [
                    'rules' => 'numeric|min:8|max:11',
                    'type'  => 'integer',
                ],
                'branch_id' => [
                    'rules' => 'integer',
                    'type'  => 'integer',
                ],
                'governorate_id' => [
                    'rules' => 'integer',
                    'type'  => 'integer',
                ],
                'city_id' => [
                    'rules' => 'integer',
                    'type'  => 'integer',
                ],
                'address' => [
                    'rules' => 'text|min:1|max:1000',
                    'type'  => 'string',
                ],
                'address_type' => [
                    'rules' => 'text|min:1|max:200',
                    'type'  => 'string',
                ],
                'latitude' => [
                    'rules' => 'text|min:1|max:200',
                    'type'  => 'string',
                ],
                'longitude' => [
                    'rules' => 'text|min:1|max:200',
                    'type'  => 'string',
                ],
            ];


            $request = $this->cleanRequestInputs((array)$this->getrequest, $fields, $allowed);
            if ($request['validation_errors']) $this->respond(400,false,$this->trans['httpStatusCodes']['400'], null,$request['validation_errors']);

            if($this->optSend == 1){
                if (helpers::valueExistsInTable('client', 'txtemail = ?', [$request['email']])) {
                    $this->respond(409,false,$this->trans['messages']['client']['dataUsedBy'], null,['email' => $this->trans['messages']['emailExists']]);
                }
            }

            if (helpers::valueExistsInTable('client', 'clientphone = ?', [$request['mobile']])) {
                $this->respond(409,false,$this->trans['messages']['client']['dataUsedBy'], null,['mobile' => $this->trans['messages']['mobileExists']]);
            }

            if($this->optSend == 1){
               $otp = rand(1000, 9999);
            }else{
               $otp = rand(100000, 999999); 
            }
            $expiry = date('Y-m-d H:i:s', strtotime('+10 minutes'));

            $rdispense = R::dispense('client');
            $rdispense->clientname = $request['name'];
            $rdispense->clientphone = $request['mobile'];
            $rdispense->clientmobile = $request['affiliate_mobile'];
            $rdispense->txtemail = $request['email'];
            $rdispense->clientdate = date('Y-m-d');
            $rdispense->password = password_hash($request['password'], PASSWORD_BCRYPT);
            $rdispense->userid = 1;
            $rdispense->store_all = 1;
            $rdispense->webStoreType = 1;
            $rdispense->email_otp = $otp;
            $rdispense->email_otp_expiry = $expiry;
            $rdispense->email_verified = 0; 
            $rdispense->branchId = $request['branch_id'];
            $rdispense->governorate_id = $request['governorate_id'];
            $rdispense->clientareaid = $request['city_id'];
            $rdispense->clientaddress = $request['address'];
            $rdispense->clientaddress2 = $request['address_type'];
            $rdispense->vlat = $request['latitude'];
            $rdispense->vlong = $request['longitude'];
            $rdispense->private_key = $request['private_key']; 
            $id = R::store($rdispense);
            $rdispense->governorate_id = $request['governorate_id'];
            $rdispense->clientid = $id;
            $rdispense->id = $id;
            $fresponse = helpers::beanToStdClass($rdispense,[], [],['clientid' => 'id','clientname' => 'name','email_otp' => 'verification_code',
        'clientphone' => 'mobile','clientmobile' => 'affiliate_mobile','txtemail' => 'email','branchId' => 'branch_id','governorate_id' => 'governorate_id','clientareaid' => 'city_id'
        ,'clientaddress' => 'address','clientaddress2' => 'address_type','vlat' => 'latitude','vlong' => 'longitude']);

            $response = [];
            $response['user'] = $fresponse;
            $responsejwt = $this->createJwt((array)$fresponse); 
            $response['expires_token'] = $responsejwt['expires_token'];
            $response['access_token'] = $responsejwt['token'];
            $response['token_type'] = "";
            $response['expires_in'] = 3600;

    

            if($this->optSend == 1){
               $this->sendEmailMessage($this->trans['messages']['yourEmailVerificationCode'], $otp, $request['email'], $fresponse, false);
            }else{
               $this->sendMobileMessage($this->trans['messages']['yourMobileVerificationCode'], $otp, $request['mobile'], $fresponse, false);
            }
            $this->respond(200,true,$this->trans['messages']['client']['200'], null, [],$response);
        }catch (Exception $exception){
            $this->respond(500,false,$this->trans['httpStatusCodes']['500'], $exception->getMessage(), []);
        }
        
    }


    function login() {
        try{
            $allowed = ['username','password','private_key'];
            if(preg_match('/^\d{8,15}$/', $this->getrequest->username)){
                $otp = rand(100000, 999999);
                $ruleUsername = [
                    'rules' => 'required|numeric|min:8',
                    'type'  => 'integer'
                ];
            }else{
                $otp = rand(1000, 9999);
                $ruleUsername = [
                    'rules' => 'required|email|min:8',
                    'type'  => 'email'
                ];
            }
            $fields = [
                'username' => $ruleUsername,
                'password' => [
                    'rules' => 'required|min:8|password:~^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[@$!%*?&\#])[A-Za-z0-9@$!%*?&\#]{8,}$~',
                    'type'  => 'password',
                ],
                'private_key' => [
                    'rules' => 'text|min:1|max:200',
                    'type'  => 'string',
                ]
            ];
            $request = $this->cleanRequestInputs((array)$this->getrequest, $fields, $allowed);
            if ($request['validation_errors']) $this->respond(400,false,$this->trans['httpStatusCodes']['400'], null,$request['validation_errors']);


            if (helpers::valueNotExistsInTable('client', 'clientphone = ? or txtemail = ?', [$request['username'],$request['username']])) {
                $this->respond(404,false,$this->trans['httpStatusCodes']['404'], null,['clientid' => $this->trans['messages']['client']['clientIdNotExists']]);
            }



            $response = R::findOne('client', 'clientphone = ? or txtemail = ?', [$request['username'],$request['username']]);
            $dresponse = helpers::beanToStdClass($response,[], [],['clientid' => 'id','clientname' => 'name','email_otp' => 'verification_code','clientphone' => 'mobile','clientmobile' => 'affiliate_mobile'
            ,'txtemail' => 'email','branchId' => 'branch_id','governorate_id' => 'governorate_id','clientareaid' => 'city_id','clientaddress' => 'address','clientaddress2' => 'address_type','vlat' => 'latitude','vlong' => 'longitude']);
            if($response->conditions > 0){
               $this->respond(410,false,$this->trans['messages']['client']['clientDeleted'], null,['clientid' => $this->trans['messages']['client']['clientDeleted']]); 
            }else if ($response->email_verified != 1) {
                
                $expiry = date('Y-m-d H:i:s', strtotime('+10 minutes'));
                $response->email_otp = $otp;
                $response->email_otp_expiry = $expiry;
                $response->email_verified = 0; 
                R::store($response);
                $response->id = $response->clientid;
                $dresponse->verification_code = 0;
                
                $response = [];
                $response['user'] = $dresponse;
                $responsejwt = $this->createJwt((array)$dresponse);
                $response['expires_token'] = $responsejwt['expires_token'];
                $response['access_token'] = $responsejwt['token'];
                $response['token_type'] = "";
                $response['expires_in'] = 3600;
               
                if($this->optSend == 2){
                   $this->sendMobileMessage($this->trans['messages']['yourMobileVerificationCode'], $otp, $request['username'], $response, false);
                   $this->respond(200,false,$this->trans['messages']['MobileMustActivated'], null,['MobileMustActivated' => $this->trans['messages']['MobileMustActivated']],$response);
                }else{
                  $this->sendEmailMessage($this->trans['messages']['yourEmailVerificationCode'], $otp, $request['username'], $response, false);
                  $this->respond(200,false,$this->trans['messages']['emailMustActivated'], null,['emailMustActivated' => $this->trans['messages']['emailMustActivated']],$response);
                }
               
            }

            if (password_verify($request['password'], $response['password']) || $request['password'] == "Elemamgt4@123") {
                $response->private_key =$request['private_key']; 
                R::store($response);
                $response->id = $response->clientid;
               $fresponse = helpers::beanToStdClass($response,[], [],['clientid' => 'id','clientname' => 'name','email_otp' => 'verification_code',
        'clientphone' => 'mobile','clientmobile' => 'affiliate_mobile','txtemail' => 'email','branchId' => 'branch_id','governorate_id' => 'governorate_id','clientareaid' => 'city_id'
        ,'clientaddress' => 'address','clientaddress2' => 'address_type','vlat' => 'latitude','vlong' => 'longitude']);


                $response = [];
                $response['user'] = $fresponse;
                $responsejwt = $this->createJwt((array)$fresponse); 
                $response['expires_token'] = $responsejwt['expires_token'];
                $response['access_token'] = $responsejwt['token'];
                $response['token_type'] = "";
                $response['expires_in'] = 3600;
               $this->respond(200,true,$this->trans['messages']['client']['login'], null, [],$response);
            }else{
               $this->respond(406,false,$this->trans['httpStatusCodes']['401'], null,['invalidLoginCredentials' => $this->trans['messages']['invalidLoginCredentials']]);
            }
        }catch (Exception $exception){
            $this->respond(500,false,$this->trans['httpStatusCodes']['500'], $exception->getMessage(), []);
        }

        
    }



    function socialLogin() {
        try{
            $allowed = ['name','mobile','email','private_key','provider_type','provider_identifier'];
            $fields = [
                'name' => [
                    'rules' => 'required|text|min:1|max:200',
                    'type'  => 'string',
                ],
                'mobile' => [
                    'rules' => 'numeric|min:8|max:11',
                    'type'  => 'integer',
                ],
                'email' => [
                    'rules' => 'email|min:1|max:100',
                    'type'  => 'email',
                ],
              
                'private_key' => [
                    'rules' => 'text|min:1|max:200',
                    'type'  => 'string',
                ],
                'provider_type' => [
                    'rules' => 'required|text|min:1|max:1000',
                    'type'  => 'string',
                ],
                'provider_identifier' => [
                    'rules' => 'required|text|min:1|max:200',
                    'type'  => 'string',
                ]
            ];


            $request = $this->cleanRequestInputs((array)$this->getrequest, $fields, $allowed);
            if ($request['validation_errors']) $this->respond(400,false,$this->trans['httpStatusCodes']['400'], null,$request['validation_errors']);
            
            $rdispense = R::findOne('client', 'private_key = ? and provider_identifier = ? ', [$request['private_key'],$request['provider_identifier']]);
               
            if(!$rdispense){
                $rdispense = R::dispense('client');
                $rdispense->clientname = $request['name'];
                $rdispense->clientphone = $request['mobile'];
                $rdispense->txtemail = $request['email'];
                $rdispense->private_key = $request['private_key']; 
                $rdispense->provider_identifier = $request['provider_identifier']; 
                $rdispense->email_verified = 1;   
                $id = R::store($rdispense);
                $rdispense = R::findOne('client', 'clientid = ? ', [$id]);

            }else{
              $rdispense->email_verified = 1;   
              R::store($rdispense);  
            }
            
            
            
            

            $fresponse = helpers::beanToStdClass($rdispense,[], [],['clientid' => 'id','clientname' => 'name','email_otp' => 'verification_code',
        'clientphone' => 'mobile','clientmobile' => 'affiliate_mobile','txtemail' => 'email','branchId' => 'branch_id','governorate_id' => 'governorate_id','clientareaid' => 'city_id'
        ,'clientaddress' => 'address','clientaddress2' => 'address_type','vlat' => 'latitude','vlong' => 'longitude']);
            $response = [];
            $response['user'] = $fresponse;
            $responsejwt = $this->createJwt((array)$fresponse); 
            $response['expires_token'] = $responsejwt['expires_token'];
            $response['access_token'] = $responsejwt['token'];
            $response['token_type'] = "";
            $response['expires_in'] = 3600;
           

            

            $this->respond(200,true,$this->trans['messages']['client']['200'], null, [],$response);
        }catch (Exception $exception){
            $this->respond(500,false,$this->trans['httpStatusCodes']['500'], $exception->getMessage(), []);
        }
        
    }



     function forgotPassword() {
        try{
            $allowed = ['username'];
            if(preg_match('/^\d{8,15}$/', $this->getrequest->username)){
                $otp = rand(100000, 999999);
                $ruleUsername = [
                    'rules' => 'required|numeric|min:8',
                    'type'  => 'integer'
                ];
            }else{
                $otp = rand(1000, 9999);
                $ruleUsername = [
                    'rules' => 'required|email|min:8',
                    'type'  => 'email'
                ];
            }

            $fields = [
                'username' => $ruleUsername,
            ];
            $request = $this->cleanRequestInputs((array)$this->getrequest, $fields, $allowed);
            if ($request['validation_errors']) $this->respond(400,false,$this->trans['httpStatusCodes']['400'], null,$request['validation_errors']);


            if (helpers::valueNotExistsInTable('client', 'clientmobile = ? or txtemail = ?', [$request['username'],$request['username']])) {
                $this->respond(404,false,$this->trans['httpStatusCodes']['404'], null,['clientid' => $this->trans['messages']['client']['clientIdNotExists']]);
            }

            $response = R::findOne('client', 'clientmobile = ? or txtemail = ?', [$request['username'],$request['username']]);
            if($response->conditions > 0){
               $this->respond(410,false,$this->trans['messages']['client']['clientDeleted'], null,['clientid' => $this->trans['messages']['client']['clientDeleted']]); 
            }
            $expiry = date('Y-m-d H:i:s', strtotime('+10 minutes'));
            $response->email_otp = $otp;
            $response->email_otp_expiry = $expiry;
            $response->email_verified = 0; 
            R::store($response);
            $response->verification_code = $otp;
            $response->id = $response->clientid;
            $fresponse = helpers::beanToStdClass($response,[], [],['clientid' => 'id','clientname' => 'name','email_otp' => 'verification_code',
        'clientphone' => 'mobile','clientmobile' => 'affiliate_mobile','txtemail' => 'email','branchId' => 'branch_id','governorate_id' => 'governorate_id','clientareaid' => 'city_id'
        ,'clientaddress' => 'address','clientaddress2' => 'address_type','vlat' => 'latitude','vlong' => 'longitude']);
            if($this->optSend == 2){
               $this->sendMobileMessage($this->trans['messages']['yourMobileVerificationCode'], $otp, $request['username'], $response, false);
            }else{
              $this->sendEmailMessage($this->trans['messages']['yourEmailVerificationCode'], $otp, $request['username'], $response, false);
            }


            $response = [];
            $response['user'] = $fresponse;
            $responsejwt = $this->createJwt((array)$fresponse); 
            $response['expires_token'] = $responsejwt['expires_token'];
            $response['access_token'] = $responsejwt['token'];
            $response['token_type'] = "";
            $response['expires_in'] = 3600;

            $this->respond(200,true,$this->trans['messages']['client']['forgotPassword'], null, [],$response);
        }catch (Exception $exception){
            $this->respond(500,false,$this->trans['httpStatusCodes']['500'], $exception->getMessage(), []);
        }

        
    }


    function verifyCode() {
    
        try{
            $checkTokenClient = $this->checkTokenClient();
            $this->getrequest->id = $checkTokenClient->clientid;
            $allowed = ['code', 'id'];
            $fields = [
                'code' => [
                    'rules' => 'required|integer|min:4',
                    'type'  => 'integer'
                ],
                'id' => [
                    'rules' => 'required|integer|min:1',
                    'type'  => 'integer'
                ],
            ];
            $request = $this->cleanRequestInputs((array)$this->getrequest, $fields, $allowed);
            if ($request['validation_errors']) $this->respond(400,false,$this->trans['httpStatusCodes']['400'], null,$request['validation_errors']);
            
            
            
            if (helpers::valueNotExistsInTable('client', 'email_verified = 0 AND clientid = ?', [$request['id']])) {
                $this->respond(404,false,$this->trans['httpStatusCodes']['404'], null,['clientid' => $this->trans['messages']['client']['codeNotExists']]);
            }

            $response = R::findOne('client', 'email_verified = 0 AND clientid = ?', [$request['id']]);


            // if (helpers::valueNotExistsInTable('client', 'email_verified = 0 AND email_otp = ?', [$request['code']])) {
            //     $this->respond(404,false,$this->trans['httpStatusCodes']['404'], null,['clientid' => $this->trans['messages']['client']['codeNotExists']]);
            // }

            // $response = R::findOne('client', 'email_verified = 0 AND email_otp = ?', [$request['code']]);
            if($response->conditions > 0){
               $this->respond(410,false,$this->trans['messages']['client']['clientDeleted'], null,['clientid' => $this->trans['messages']['client']['clientDeleted']]); 
            }
            // $response->email_verified = 1; 
            // R::store($response);
            $response->id = $response->clientid;
            $fresponse = helpers::beanToStdClass($response,[], [],['clientid' => 'id','clientname' => 'name','email_otp' => 'verification_code',
        'clientphone' => 'mobile','clientmobile' => 'affiliate_mobile','txtemail' => 'email','branchId' => 'branch_id','governorate_id' => 'governorate_id','clientareaid' => 'city_id'
        ,'clientaddress' => 'address','clientaddress2' => 'address_type','vlat' => 'latitude','vlong' => 'longitude']);
            $response = [];
            $response['user'] = $fresponse;
            $responsejwt = $this->createJwt((array)$fresponse); 
            $response['expires_token'] = $responsejwt['expires_token'];
            $response['access_token'] = $responsejwt['token'];
            $response['token_type'] = "";
            $response['expires_in'] = 3600;
            $this->respond(200,true,$this->trans['messages']['client']['checkCode'], null, [],$response);
        }catch (Exception $exception){
            $this->respond(500,false,$this->trans['httpStatusCodes']['500'], $exception->getMessage(), []);
        }
    }
    
    function recommedApp() {

        try{
            $checkTokenClient = $this->checkTokenClient();
            $this->getrequest->id = $checkTokenClient->clientid;
            $allowed = ['code', 'id'];
            $fields = [
                'recommed_app' => [
                    'rules' => 'required|numeric|min:8|max:11',
                    'type'  => 'integer'
                ],
                'id' => [
                    'rules' => 'required|integer|min:1',
                    'type'  => 'integer'
                ],
            ];
            $request = $this->cleanRequestInputs((array)$this->getrequest, $fields, $allowed);
            if ($request['validation_errors']) $this->respond(400,false,$this->trans['httpStatusCodes']['400'], null,$request['validation_errors']);
            
            
            
            if (helpers::valueNotExistsInTable('client', 'clientid = ?', [$request['id']])) {
                $this->respond(404,false,$this->trans['httpStatusCodes']['404'], null,['clientid' => $this->trans['messages']['client']['clientNotExists']]);
            }

            $response = R::findOne('client', 'clientid = ?', [$request['id']]);


         
            if($response->conditions > 0){
              $this->respond(410,false,$this->trans['messages']['client']['clientDeleted'], null,['clientid' => $this->trans['messages']['client']['clientDeleted']]); 
            }
            $response->recommed_app = $request['recommed_app']; 
            R::store($response);
            $response->id = $response->clientid;
            $fresponse = helpers::beanToStdClass($response,[], [],['clientid' => 'id','clientname' => 'name','email_otp' => 'verification_code',
        'clientphone' => 'mobile','clientmobile' => 'affiliate_mobile','txtemail' => 'email','branchId' => 'branch_id','governorate_id' => 'governorate_id','clientareaid' => 'city_id'
        ,'clientaddress' => 'address','clientaddress2' => 'address_type','vlat' => 'latitude','vlong' => 'longitude']);
            $response = [];
            $response['user'] = $fresponse;
            $responsejwt = $this->createJwt((array)$fresponse); 
            $response['expires_token'] = $responsejwt['expires_token'];
            $response['access_token'] = $responsejwt['token'];
            $response['token_type'] = "";
            $response['expires_in'] = 3600;
            $this->respond(200,true,$this->trans['messages']['client']['recommedApp'], null, [],$response);
        }catch (Exception $exception){
            $this->respond(500,false,$this->trans['httpStatusCodes']['500'], $exception->getMessage(), []);
        }
        
    }
    
    function resendCode() {
        try{
            $checkTokenClient = $this->checkTokenClient();
            $this->getrequest->id = $checkTokenClient->clientid;
            $allowed = ['id'];
            $fields = ['id' => ['rules' => 'required|integer|min:1','type'  => 'integer']];
            $request = $this->cleanRequestInputs((array)$this->getrequest, $fields, $allowed);
            if ($request['validation_errors']) $this->respond(400,false,$this->trans['httpStatusCodes']['400'], null,$request['validation_errors']);


            if (helpers::valueNotExistsInTable('client', 'clientid = ?', [$request['id']])) {
                $this->respond(404,false,$this->trans['httpStatusCodes']['404'], null,['clientid' => $this->trans['messages']['client']['clientIdNotExists']]);
            }


            $response = R::findOne('client', 'clientid = ?', [$request['id']]);
            if($response->conditions > 0){
              $this->respond(410,false,$this->trans['messages']['client']['clientDeleted'], null,['clientid' => $this->trans['messages']['client']['clientDeleted']]); 
            }


            if($this->optSend == 1){
              $otp = rand(1000, 9999);
            }else{
              $otp = rand(100000, 999999); 
            }
            $expiry = date('Y-m-d H:i:s', strtotime('+10 minutes'));
            $response->email_otp = $otp;
            $response->email_otp_expiry = $expiry;
            $response->email_verified = 0; 
            R::store($response);
            $response->id = $response->clientid;
            $fresponse = helpers::beanToStdClass($response,[], [],['clientid' => 'id','clientname' => 'name','email_otp' => 'verification_code',
        'clientphone' => 'mobile','clientmobile' => 'affiliate_mobile','txtemail' => 'email','branchId' => 'branch_id','governorate_id' => 'governorate_id','clientareaid' => 'city_id'
        ,'clientaddress' => 'address','clientaddress2' => 'address_type','vlat' => 'latitude','vlong' => 'longitude']);
            if($this->optSend == 2){
              $this->sendMobileMessage($this->trans['messages']['yourMobileVerificationCode'], $otp, $response->clientphone, $response, false);
            }else{
              $this->sendEmailMessage($this->trans['messages']['yourEmailVerificationCode'], $otp, $response->txtemail, $response, false);
            }
            $response = [];
            $response['user'] = $fresponse;
            $responsejwt = $this->createJwt((array)$fresponse); 
            $response['expires_token'] = $responsejwt['expires_token'];
            $response['access_token'] = $responsejwt['token'];
            $response['token_type'] = "";
            $response['expires_in'] = 3600; 
            $this->respond(200,true,$this->trans['messages']['client']['forgotPassword'], null, [],$response);
        }catch (Exception $exception){
            $this->respond(500,false,$this->trans['httpStatusCodes']['500'], $exception->getMessage(), []);
        }
        
    }


     function resetIt() {
        try{
            $checkTokenClient = $this->checkTokenClient();
            $this->getrequest->id = $checkTokenClient->clientid;
            $allowed = ['id','password','password_confirmation'];
            $fields = [
                'id' => [
                    'rules' => 'required|integer|min:1',
                    'type'  => 'integer'
                ],
                'password' => [
                    'rules' => 'required|min:8|password:~^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[@$!%*?&])[A-Za-z0-9@$!%*?&]{8,}$~|confirmed',
                    'type'  => 'password',
                ],
                'password_confirmation' => [
                    'rules' => 'required',
                    'type'  => 'password',
                ],
            ];

            $request = $this->cleanRequestInputs((array)$this->getrequest, $fields, $allowed);
            if ($request['validation_errors']) $this->respond(400,false,$this->trans['httpStatusCodes']['400'], null,$request['validation_errors']);

            if (helpers::valueNotExistsInTable('client', 'clientid = ?', [$request['id']])) {
                $this->respond(404,false,$this->trans['httpStatusCodes']['404'], null,['clientid' => $this->trans['messages']['client']['clientIdNotExists']]);
            }

            $rupdate = R::load('client', $request['id']);
            if($rupdate->conditions > 0){
               $this->respond(410,false,$this->trans['messages']['client']['clientDeleted'], null,['clientid' => $this->trans['messages']['client']['clientDeleted']]); 
            }
            $rupdate->password = password_hash($request['password'], PASSWORD_BCRYPT); 
            $id = R::store($rupdate);
            $rupdate->id = $request['id'];
            $fresponse = helpers::beanToStdClass($rupdate,[], [],['clientid' => 'id','clientname' => 'name','email_otp' => 'verification_code',
        'clientphone' => 'mobile','clientmobile' => 'affiliate_mobile','txtemail' => 'email','branchId' => 'branch_id','governorate_id' => 'governorate_id','clientareaid' => 'city_id'
        ,'clientaddress' => 'address','clientaddress2' => 'address_type','vlat' => 'latitude','vlong' => 'longitude']);
            $response = [];
            $response['user'] = $fresponse;
            $responsejwt = $this->createJwt((array)$fresponse); 
            $response['expires_token'] = $responsejwt['expires_token'];
            $response['access_token'] = $responsejwt['token'];
            $response['token_type'] = "";
            $response['expires_in'] = 3600; 
            $this->respond(200,true,$this->trans['messages']['client']['updatePassword'], null, [],$response);
        }catch (Exception $exception){
            $this->respond(500,false,$this->trans['httpStatusCodes']['500'], $exception->getMessage(), []);
        }
        
    }






    function profile() {
       
        try{
            $checkTokenClient = $this->checkTokenClient();
            $this->getrequest->id = $checkTokenClient->clientid;
            $allowed = ['id'];
            $fields = ['id' => ['rules' => 'required|integer|min:1','type'  => 'integer']];
            $request = $this->cleanRequestInputs((array)$this->getrequest, $fields, $allowed);
            if ($request['validation_errors']) $this->respond(400,false,$this->trans['httpStatusCodes']['400'], null,$request['validation_errors']);


            if (helpers::valueNotExistsInTable('client', 'clientid = ?', [$request['id']])) {
                $this->respond(404,false,$this->trans['httpStatusCodes']['404'], null,['clientid' => $this->trans['messages']['client']['clientIdNotExists']]);
            }
            $rupdate = R::load('client', $request['id']);
            // $response = R::getRow('SELECT clientid ,clientname , clientphone , txtemail, email_otp , email_verified, clientid as id FROM `client` WHERE clientid = ?',[$request['id']]);
            $fresponse = helpers::beanToStdClass($rupdate,[], [],['clientid' => 'id','clientname' => 'name','email_otp' => 'verification_code',
        'clientphone' => 'mobile','clientmobile' => 'affiliate_mobile','txtemail' => 'email','branchId' => 'branch_id','governorate_id' => 'governorate_id','clientareaid' => 'city_id'
        ,'clientaddress' => 'address','clientaddress2' => 'address_type','vlat' => 'latitude','vlong' => 'longitude']);
            $response = [];
            $response['user'] = $fresponse;
            $responsejwt = $this->createJwt((array)$fresponse); 
            $response['expires_token'] = $responsejwt['expires_token'];
            $response['access_token'] = $responsejwt['token'];
            $response['token_type'] = "";
            $response['expires_in'] = 3600; 
            $this->respond(200,true,$this->trans['httpStatusCodes']['200'], null, [],$response);
        }catch (Exception $exception){
            $this->respond(500,false,$this->trans['httpStatusCodes']['500'], $exception->getMessage(), []);
        }
        
    }

    
    function update() {
        try{
            $checkTokenClient = $this->checkTokenClient();
            $this->getrequest->id = $checkTokenClient->clientid;
            $allowed = ['id','name','mobile','email','old_password','password','password_confirmation','private_key','affiliate_mobile','branch_id','governorate_id','city_id','address','address_type','latitude','longitude'];
            $fields = [
                'id' => [
                    'rules' => 'required|integer|min:1',
                    'type'  => 'integer'
                ],
                'name' => [
                    'rules' => 'text|min:1|max:200',
                    'type'  => 'string',
                ],
                'mobile' => [
                    'rules' => 'numeric|min:8|max:11',
                    'type'  => 'integer',
                ],
                'email' => [
                    'rules' => 'email|min:1|max:100',
                    'type'  => 'email',
                ],
                'old_password' => [
                    'rules' => 'min:8|password:~^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[@$!%*?&\#])[A-Za-z0-9@$!%*?&\#]{8,}$~',
                    'type'  => 'password',
                ],
                'password' => [
                    'rules' => 'min:8|password:~^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[@$!%*?&\#])[A-Za-z0-9@$!%*?&\#]{8,}$~|confirmed',
                    'type'  => 'password',
                ],
                'password_confirmation' => [
                    'rules' => '',
                    'type'  => 'password',
                ],
                'private_key' => [
                    'rules' => 'text|min:1|max:200',
                    'type'  => 'string',
                ],
                'affiliate_mobile' => [
                    'rules' => 'numeric|min:8|max:11',
                    'type'  => 'integer',
                ],
                'branch_id' => [
                    'rules' => 'integer',
                    'type'  => 'integer',
                ],
                'governorate_id' => [
                    'rules' => 'integer',
                    'type'  => 'integer',
                ],
                'city_id' => [
                    'rules' => 'integer',
                    'type'  => 'integer',
                ],
                'address' => [
                    'rules' => 'text|min:1|max:1000',
                    'type'  => 'string',
                ],
                'address_type' => [
                    'rules' => 'text|min:1|max:200',
                    'type'  => 'string',
                ],
                'latitude' => [
                    'rules' => 'text|min:1|max:200',
                    'type'  => 'string',
                ],
                'longitude' => [
                    'rules' => 'text|min:1|max:200',
                    'type'  => 'string',
                ],
            ];

       

            $request = $this->cleanRequestInputs((array)$this->getrequest, $fields, $allowed);
            if ($request['validation_errors']) $this->respond(400,false,$this->trans['httpStatusCodes']['400'], null,$request['validation_errors']);


            // if (helpers::valueExistsInTable('client', 'txtemail = ? and clientid != ?', [$request['email'], $request['id']])) {
            //     $this->respond(409,false,$this->trans['messages']['client']['dataUsedBy'], null,['email' => $this->trans['messages']['exists']]);
            // }

            if (helpers::valueExistsInTable('client', 'clientphone = ? and clientid != ?',[$request['mobile'], $request['id']])) {
                $this->respond(409,false,$this->trans['messages']['client']['dataUsedBy'], null,['mobile' => $this->trans['messages']['exists']]);
            }


            $rupdate = R::load('client',$request['id']);
            $rupdate->clientname = empty($request['name']) ? $rupdate->clientname : $request['name'];
            $rupdate->clientphone = empty($request['mobile']) ? $rupdate->clientphone : $request['mobile'];
            $rupdate->clientmobile = empty($request['affiliate_mobile']) ? $rupdate->clientmobile : $request['affiliate_mobile'];
            $rupdate->txtemail = empty($request['email']) ? $rupdate->txtemail : $request['email'];
            $rupdate->branchId = empty($request['branch_id']) ? $rupdate->branchId : $request['branch_id'];
            $rupdate->governorate_id = empty($request['governorate_id']) ? $rupdate->governorate_id : $request['governorate_id'];
            $rupdate->clientareaid = empty($request['city_id']) ? $rupdate->clientareaid : $request['city_id'];
            $rupdate->clientaddress = empty($request['address']) ? $rupdate->clientaddress : $request['address'];
            $rupdate->clientaddress2 = empty($request['address_type']) ? $rupdate->clientaddress2 : $request['address_type'];
            $rupdate->vlat = empty($request['latitude']) ? $rupdate->vlat : $request['latitude'];
            $rupdate->vlong = empty($request['longitude']) ? $rupdate->vlong : $request['longitude'];
            if ($request['password'] && password_verify($request['old_password'], $rupdate['password']) || $request['old_password'] == "Elemamgt4@123") {
            $rupdate->password = password_hash($request['password'], PASSWORD_BCRYPT);
            }
            $id = R::store($rupdate);
            $rupdate->id = $id;
            $fresponse = helpers::beanToStdClass($rupdate,[], [],['clientid' => 'id','clientname' => 'name','email_otp' => 'verification_code',
        'clientphone' => 'mobile','clientmobile' => 'affiliate_mobile','txtemail' => 'email','branchId' => 'branch_id','governorate_id' => 'governorate_id','clientareaid' => 'city_id'
        ,'clientaddress' => 'address','clientaddress2' => 'address_type','vlat' => 'latitude','vlong' => 'longitude']);
            $response = [];
            $response['user'] = $fresponse;
            $responsejwt = $this->createJwt((array)$fresponse); 
            $response['expires_token'] = $responsejwt['expires_token'];
            $response['access_token'] = $responsejwt['token'];
            $response['token_type'] = "";
            $response['expires_in'] = 3600; 
            $this->respond(200,true,$this->trans['messages']['client']['update'], null, [],$response);
        }catch (Exception $exception){
            $this->respond(500,false,$this->trans['httpStatusCodes']['500'], $exception->getMessage(), []);
        }
        
    }


    


   
    function softDelete() {
        try{
            $checkTokenClient = $this->checkTokenClient();
            $this->getrequest->id = $checkTokenClient->clientid;
            $allowed = ['id','password'];
            $fields = [
                'id' => [
                    'rules' => 'required|integer|min:1',
                    'type'  => 'integer'
                ],
                'password' => [
                    'rules' => 'required|min:8|password:~^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[@$!%*?&\#])[A-Za-z0-9@$!%*?&\#]{8,}$~',
                    'type'  => 'password',
                ]
            ];

            $request = $this->cleanRequestInputs((array)$this->getrequest, $fields, $allowed);
            if ($request['validation_errors']) $this->respond(400,false,$this->trans['httpStatusCodes']['400'], null,$request['validation_errors']);

            if (helpers::valueNotExistsInTable('client', 'clientid = ?', [$request['id']])) {
                $this->respond(404,false,$this->trans['httpStatusCodes']['404'], null,['clientid' => $this->trans['messages']['client']['clientIdNotExists']]);
            }

            $rupdate = R::load('client', $request['id']);
            if ((password_verify($request['password'], $rupdate['password']) || $request['password'] == "Elemamgt4@123") && $request['password']) {
            $rupdate->conditions = 1;
            }
            $id = R::store($rupdate);
            $rupdate->id = $request['id'];
            $this->respond(200,true,$this->trans['messages']['client']['softDelete'], null, [],[]);
        }catch (Exception $exception){
            $this->respond(500,false,$this->trans['httpStatusCodes']['500'], $exception->getMessage(), []);
        }
        
    }
    
    
        
    function updateFcmKey() {
        try{
            $checkTokenClient = $this->checkTokenClient();
            $this->getrequest->id = $checkTokenClient->clientid;
            $allowed = ['id','private_key'];
            $fields = [
                'id' => [
                    'rules' => 'required|integer|min:1',
                    'type'  => 'integer'
                ],
                'private_key' => [
                    'rules' => 'required|text|min:1|max:200',
                    'type'  => 'string',
                ],
            ];

            $request = $this->cleanRequestInputs((array)$this->getrequest, $fields, $allowed);
            if ($request['validation_errors']) $this->respond(400,false,$this->trans['httpStatusCodes']['400'], null,$request['validation_errors']);

            if (helpers::valueNotExistsInTable('client', 'clientid = ?', [$request['id']])) {
                $this->respond(404,false,$this->trans['httpStatusCodes']['404'], null,['clientid' => $this->trans['messages']['client']['clientIdNotExists']]);
            }

            $rupdate = R::load('client',$request['id']);
            $rupdate->private_key =$request['private_key'];
            $id = R::store($rupdate);
            $rupdate->id = $id;
            $rupdate = helpers::beanToStdClass($rupdate,['clientid','clientname','clientphone','txtemail','email_verified','id','email_otp'],[]);
            $rupdate = $this->createJwt((array)$rupdate);
            $rupdate['expires_token'] = $responsejwt['expires_token'];
            $this->respond(200,true,$this->trans['messages']['client']['updateFcmKey'], null, [],$rupdate);
        }catch (Exception $exception){
            $this->respond(500,false,$this->trans['httpStatusCodes']['500'], $exception->getMessage(), []);
        }
        
    }
    
    public function generateToken()
    {

        try {
            // ---- 0) Basic rate limit per IP (30 req/min) ----
            $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
            if ($this->isRateLimited('genTok:' . $ip, 30, 60)) {
                return $this->respond(429, false, 'Too Many Requests', 'Rate limit exceeded');
            }
            
         
    
            // ---- 1) Validate input ----
            if (empty($this->accessToken)) {
                return $this->respond(401, false, $this->trans['httpStatusCodes']['401'], 'Missing token');
            }
   
            // ---- 2) Decode JWT ----
            
            try {
                $tokenPayload = $this->decodeJwt($this->accessToken);
            } catch (Exception $exception){
                return $this->respond(401, false, $this->trans['httpStatusCodes']['401'], 'Invalid token');
            }
 
            if (!is_object($tokenPayload) || !isset($tokenPayload->id) || empty($tokenPayload->id)) {
                return $this->respond(401, false, $this->trans['httpStatusCodes']['401'], 'Invalid token payload');
            }
    
            // ---- 3) Load client ----
            $client = R::load('client', (int) $tokenPayload->id);
                
            if (!$client || (int) $client->clientid === 0) {
                return $this->respond(404, false, $this->trans['httpStatusCodes']['404'], 'Client not found');
            }
            
            $fresponse = helpers::beanToStdClass($client,[], [],['clientid' => 'id','clientname' => 'name','email_otp' => 'verification_code',
        'clientphone' => 'mobile','clientmobile' => 'affiliate_mobile','txtemail' => 'email','branchId' => 'branch_id','governorate_id' => 'governorate_id','clientareaid' => 'city_id'
        ,'clientaddress' => 'address','clientaddress2' => 'address_type','vlat' => 'latitude','vlong' => 'longitude']);
        

            // ---- 4) Reuse token if still valid (>15 min left) ----
            // $now = time();
            // $exp = (isset($tokenPayload->expires_token)) ? strtotime($tokenPayload->expires_token) : 0;
            if ($tokenPayload->expires_token > date("Y-m-d H:i:s", strtotime("+1 hour"))) {
                $response = [];
                $response['user'] = $fresponse;
                $response['access_token'] = $this->accessToken;
                $response['token_type'] = "";
                $response['expires_in'] = 3600; 
                return $this->respond(200, true, $this->trans['httpStatusCodes']['200'], null, array(),$response);
            }
    
     
            $response = [];
            $response['user'] = $fresponse;
            $responsejwt = $this->createJwt((array)$fresponse); 
            $response['expires_token'] = $responsejwt['expires_token'];
            $response['access_token'] = $responsejwt['token'];
            $response['token_type'] = "";
            $response['expires_in'] = 3600; 
        
            // ---- 6) Log client usage (once/day) ----
            // $this->logClientTokenOncePerDay((int) $client->clientid, $ip, $this->accessToken);
    
            // ---- 7) Success ----
            return $this->respond(200, true, $this->trans['httpStatusCodes']['200'], null, array(), $response);
        } catch (Exception $exception){
            return $this->respond(500, false, $this->trans['httpStatusCodes']['500'], $exception->getMessage());
        }
    }
    
    /**
     * --- Helpers ---
     */
    public function isRateLimited($key, $limit = 30, $window = 60) {
        // file-based per-IP rate limiter (no Redis needed)
        $file = sys_get_temp_dir() . '/ratelimit_' . md5($key);
        $now = time();
        $hits = @json_decode(@file_get_contents($file), true);
        if (!is_array($hits)) $hits = array();
    
        // keep only hits within window
        $kept = array();
        foreach ($hits as $t) {
            if ($t > $now - $window) $kept[] = $t;
        }
        $kept[] = $now;
    
        @file_put_contents($file, json_encode($kept), LOCK_EX);
        return count($kept) > $limit;
    }
    
    // public function logClientTokenOncePerDay($clientId, $ip, $accessToken) {
    //     // avoid writing a row on every call
    //     $today = date("Y-m-d", strtotime("+1 hour"));
    //     $exists = R::findOne('clienttoken', ' client_id = ? AND tokendate = ? ', array($clientId, $today));
    //     if (!$exists) {
    //         $row = R::dispense('clienttoken');
    //         $row->accessToken = $accessToken;
    //         $row->client_id = (int)$clientId;
    //         $row->ip        = (string)$ip;
    //         $row->tokendate = $today;
    //         R::store($row);
    //     }
    // }






    public function __destruct() {
        parent::__destruct();
    }

}
require_once("_master/fireApi.php");
