<?php
namespace App\Controllers\MqttServices\Auth;

use App\Controllers\BaseController;
use Models\ServiceAuthenticationsModel;
use Models\UserDeviceInfoModel;
use Models\UserGatewaysModel;

require_once APPPATH . 'Libraries/ServiceErrors.php';

class MqttServiceAuth extends BaseController {

    public $g_arrmixRequestParameterDetails;
    public $g_arrmixDecryptedTokenDetails;
    public $g_intAppVersion;
    public $g_strConsumer;
    public $g_strMethodName;
    public $g_strOriginalMethodName;
    public $g_arrmixAuthDetails;
    public $g_strReceivedTopic;

    public $g_arrmixSkipMethod = ['authentication'];

    public function __construct(  $arrmixRequestRawData ) {
		
        $this->loadConfigurations();

        $this->loadRequestRawData( $arrmixRequestRawData );

        $this->validateToken();
	}

    public function validateToken() {

        if( 'otp' == $this->getRequestOriginalMethodName() ) {
            
            if( false == isset( $this->g_arrmixAuthDetails['token'] ) || false == isVal( $this->g_arrmixAuthDetails['token'] ) ) {
                $this->generateMqttError( 'error', ERROR_ACCESS_TOKEN_NOT_FOUND, 'Access token not found.' );
            }
            
            try {
                $arrmixDecryptTokenData = $this->decryptToken( $this->g_arrmixAuthDetails['token'] );
            } catch( \RuntimeException $objException ) {
                $this->generateMqttError( self::MSGID_DATA, ERROR_INVALID_ACCESS_TOKEN, $objException->getMessage() );
            }
            
            if( false == isValArr( $arrmixDecryptTokenData ) || 
                ( true == isValArr( $arrmixDecryptTokenData ) && 
                    ( 
                        false == isset( $arrmixDecryptTokenData['user_id'] ) || false == isset( $arrmixDecryptTokenData['user_type_id'] ) || false == isset( $arrmixDecryptTokenData['login_at'] ) ||
                        false == isValId( $arrmixDecryptTokenData['user_id'] ) || false == isValId( $arrmixDecryptTokenData['user_type_id'] )
                    ) 
                ) 
            ) {
                $this->generateMqttError( self::MSGID_DATA, ERROR_INVALID_ACCESS_TOKEN, ERROR_TYPE_MESSAGE_INVALID_TOKEN );
            }
    
            $arrmixUserDetails = \Models\UsersModel::createService()->where( ['user_id' => $arrmixDecryptTokenData['user_id'], 'user_type_id' => $arrmixDecryptTokenData['user_type_id'] ] )->first();
                
            if( false == isValArr( $arrmixUserDetails ) ) {
                $this->generateMqttError( self::MSGID_DATA, ERROR_INVALID_ACCESS_TOKEN, 'User not found.', ERROR_TYPE_MESSAGE_INVALID_TOKEN );
            }
    
            $arrmixUserDeviceInfoDetails = UserDeviceInfoModel::createService()->where( 'user_device_info_id', $arrmixDecryptTokenData['user_device_info_id'] )->first();
            
            if( false == isValArr( $arrmixUserDeviceInfoDetails ) ) {
                $this->generateMqttError( self::MSGID_DATA, ERROR_INVALID_IMEI, 'imei not found.', ERROR_TYPE_MESSAGE_INVALID_TOKEN );
            }
    
            if( strtotime( CURRENT_DATETIME ) > $arrmixDecryptTokenData['expired_at'] ) {
                $this->generateMqttError( self::MSGID_DATA, ERROR_ACCESS_TOKEN_EXPIRED, 'Access token has been exipred.' );
            }
        } else {

            $arrmixServiceAuthenticationDetails = ServiceAuthenticationsModel::createService()->findServiceAuthenticationByOtp( $this->g_arrmixAuthDetails['otp'] );
            
            if( false == isValArr( $arrmixServiceAuthenticationDetails ) ) {
                $this->generateMqttError( self::MSGID_DATA, ERROR_INVALID_OTP, ERROR_TYPE_MESSAGE_INVALID_OTP,  );
            }

            if( strtotime( CURRENT_DATETIME ) > strtotime( $arrmixServiceAuthenticationDetails['expired_at'] ) ) {
                $this->generateMqttError( self::MSGID_DATA, ERROR_OTP_EXPIRED, 'OTP has been exipred.' );
            }

            $arrmixDecryptTokenData = [
                'user_id'      => $arrmixServiceAuthenticationDetails['user_id'],
                'user_type_id' => $arrmixServiceAuthenticationDetails['user_type_id'],
                'username'     => $arrmixServiceAuthenticationDetails['username'],
                'fullname'     => $arrmixServiceAuthenticationDetails['first_name'] . ' ' . $arrmixServiceAuthenticationDetails['last_name'],
                'imei_number'  => $arrmixServiceAuthenticationDetails['imei_number'],
                'expired_at'   => strtotime( $arrmixServiceAuthenticationDetails['expired_at'] )
            ];

        }

        $this->setDecryptedTokenDetails( $arrmixDecryptTokenData );
        
        return true;

    }

    public function loadRequestRawData( $arrmixRequestRawData ) {

        $this->setRequestAuthDetails( $arrmixRequestRawData['auth'] );
        $this->setRequestMethodName( $arrmixRequestRawData['method'] );
        $this->setRequestParameterDetails( $arrmixRequestRawData['params'] );
        $this->setPayload( $arrmixRequestRawData['payload'] );
        $this->setReceivedTopic( $arrmixRequestRawData['received_topic'] );
    }

    public function setRequestMethodName( $strMethodName ) {

        $this->setRequestOriginalMethodName( $strMethodName );

        $strConvertMethodName = 'action' . str_replace( '_', '', ucwords( $strMethodName, '_' ) );
        
        $this->g_strMethodName = $strConvertMethodName;
    }
    
    public function getRequestMethodName() {
        return $this->g_strMethodName;
    }

    public function setRequestOriginalMethodName( $strMethodName ) {
        $this->g_strOriginalMethodName = $strMethodName;
    }
    
    public function getRequestOriginalMethodName() {
        return $this->g_strOriginalMethodName;
    }
    
    public function setPayload( $strPayload ) {
        $this->g_strPayload = $strPayload;
    }

    public function setReceivedTopic( $strReceivedTopic ) {
        $this->g_strReceivedTopic = $strReceivedTopic;
    }

    public function setDecryptedTokenDetails( $arrmixDecryptTokenData ) {
        $this->g_arrmixDecryptedTokenDetails = $arrmixDecryptTokenData;
    }

    public function setRequestParameterDetails( $arrmixParameterDetails ) {
        $this->g_arrmixRequestParameterDetails = $arrmixParameterDetails;
    }

    public function setRequestAuthDetails( $arrmixAuthDetails ) {
        $this->g_arrmixAuthDetails = $arrmixAuthDetails;
    }

}
