<?php

namespace Teknisa\Libs\Controller;

use Teknisa\Libs\Exception\CustomException;
use Teknisa\Libs\Util\Utilities;
use Teknisa\Libs\Util\InstanceProvider;
use Zeedhi\Framework\DTO\Request;
use Zeedhi\Framework\DTO\Response;
use Zeedhi\Framework\DataSource\DataSet;
use Teknisa\Libs\Service\Login as LoginService;
use Teknisa\Libs\Service\Api as ApiService;
use Teknisa\Libs\Util\Utilities as LibUtilities;

class Login {
    /** @var LoginService $loginService */
    private $loginService;
    /** @var ApiService $apiService */
    private $apiService;

    /**
     * @param LoginService $loginService
     * @param ApiService $apiService
     */
    public function __construct(LoginService $loginService, ApiService $apiService) {
        $this->loginService = $loginService;
        $this->apiService   = $apiService;
    }

    /**
     * @param Request\Filter $request
     * @param Response $response
     * @throws \Exception
     */
    public function startSession(Request\Filter $request, Response $response) {
        try {
            $conditions = $request->getFilterCriteria()->getConditions();
            $isLogged   = Utilities::getValueInFilterDataSourceByName($conditions, 'IS_LOGGED');
            $loginUser  = Utilities::getValueInFilterDataSourceByName($conditions, 'USER');
            $loginToken = Utilities::getValueInFilterDataSourceByName($conditions, 'LOGIN_TOKEN');
            $loginLang  = Utilities::getValueInFilterDataSourceByName($conditions, 'LOGIN_LANGUAGE');
            $loginSep   = Utilities::getValueInFilterDataSourceByName($conditions, 'LOGIN_SEPARATOR');

            $modulesVersionError = null;
            try {
                $this->apiService->getModulesVersion();
            } catch(CustomException $e) {
                $modulesVersionError = array(
                    'MESSAGE_CODE'   => $e->getMessage(),
                    'MESSAGE_PARAMS' => $e->getParams()
                );
            }
            
            $filter = array(
                'TOKEN' => $loginToken
            );
            $redirectionData = InstanceProvider::getMongoDB()->find('LoginRedirection', $filter);
            $licenseInfo = false;
            if(!empty($redirectionData)) {
                $loginUser = $redirectionData[0]['USER'];
                if(!empty($redirectionData[0]['LICENSE_INFO'])) {
                    $licenseInfo = $redirectionData[0]['LICENSE_INFO'];
                }
                InstanceProvider::getMongoDB()->remove('LoginRedirection', $filter);
            }

            $loginUserInfo = @json_decode(LibUtilities::zeedhiDecrypt($loginUser), true);
            if(empty($loginUserInfo)) {
                $loginUserInfo = InstanceProvider::getSession()->get('LOGIN_USER_INFO');
            } else {
                unset($loginUserInfo['CURRENT_SECONDS']);
            }
            if(isset($loginUserInfo['USER_DATA']) && !empty($loginUserInfo['USER_DATA'])) {
                $userData = $loginUserInfo['USER_DATA'];
            } else {
                $userData = $this->apiService->getUserData($loginUserInfo['USER_EMAIL'], null);
            }

            $noticeForOperatorData = InstanceProvider::getMongoDB()->find('LoginNoticeForOperator', $filter);
            $notices = [];
            $timeOutNotices = [];
            if(!empty($noticeForOperatorData)) {
                $notices = $noticeForOperatorData[0]['NOTICES'];
                $timeOutNotices = $noticeForOperatorData[0]['TIMEOUTNOTICES'];
            }
            $userData = $this->loginService->restoreSession($userData, $loginUserInfo, $isLogged, $modulesVersionError, 
                $loginToken, $loginLang, $loginSep,$notices, $timeOutNotices);
            $userData['LICENSE_INFO'] = $licenseInfo;
            $response->addDataSet(new DataSet('system', $userData));
        } catch(CustomException $e) {
            $response->setError(Utilities::getErrorObjectFromException($e));
        }
    }

    /**
     * @param Request\Filter $request
     * @param Response $response
     * @throws \Exception
     */
    public function logout(Request\Filter $request, Response $response) {
        try {
            $conditions = $request->getFilterCriteria()->getConditions();
            $project    = Utilities::getValueInFilterDataSourceByName($conditions, 'PROJECT');
            $eraseHash  = Utilities::getValueInFilterDataSourceByName($conditions, 'ERASE_HASH');
            $hash       = Utilities::getValueInFilterDataSourceByName($conditions, 'HASH');
            $this->loginService->logout($project, $eraseHash, $hash);
        } catch(\Exception $e) {
            $response->setError(new Response\Error($e->getMessage(), Response\Message::TYPE_ERROR));
        }
    }

    /**
     * @param Request\Filter $request
     * @param Response $response
     * @throws \Exception
     */
    public function validateExpiredSession(Request\Filter $request, Response $response) {
        try {
            $conditions  = $request->getFilterCriteria()->getConditions();
            $timeout     = Utilities::getValueInFilterDataSourceByName($conditions, 'TIMEOUT');
            $sessionInfo = $this->loginService->validateExpiredSession($timeout);
            $response->addDataSet(new DataSet('expiredSessionInfo', $sessionInfo));
        } catch(\Exception $e) {
            $response->setError(new Response\Error($e->getMessage(), Response\Message::TYPE_ERROR));
        }
    }

    /**
     * @param Request\Filter $request
     * @param Response $response
     * @throws \Exception
     */
    public function updateSession(Request\Filter $request, Response $response) {
        try {
            $conditions         = $request->getFilterCriteria()->getConditions();
            $user               = Utilities::getValueInFilterDataSourceByName($conditions, 'USER');
            $accessProfile      = Utilities::getValueInFilterDataSourceByName($conditions, 'ACCESS_PROFILE');
            $otherSessionValues = Utilities::getValueInFilterDataSourceByName($conditions, 'OTHER_SESSION_VALUES');
            $loginUser          = Utilities::getValueInFilterDataSourceByName($conditions, 'LOGIN_USER');
            $userSession        = $this->loginService->updateSession($user, $accessProfile, $otherSessionValues, $loginUser);
            $response->addDataSet(new DataSet('sessionUpdated', $userSession));
        } catch(\Exception $e) {
            $response->setError(new Response\Error($e->getMessage(), Response\Message::TYPE_ERROR));
        }
    }

    /**
     * @param Request\Filter $request
     * @param Response $response
     * @throws \Exception
     */
    public function saveCollectedData(Request\DataSet $request, Response $response){
        try {
            $row            = $request->getDataSet()->getRows()[0];
            $collectionIds  = $row['COLLECTION_IDS'];
            $operationId    = $row['OPERATION_ID'];
            $productId      = $row['PRODUCT_ID'];
            $operatorCode   = $row['OPERATOR_CODE'];
            $operatorName   = $row['OPERATOR_NAME'];
            $organizationId = $row['ORGANIZATION_ID'];
            Utilities::saveCollectedData($collectionIds, $operationId, $productId, $operatorCode, $operatorName, $organizationId);
        } catch(\Exception $e) {
            $response->setError(new Response\Error($e->getMessage(), Response\Message::TYPE_ERROR));
        }
    }

    /**
     * @param Request\Filter $request
     * @param Response $response
     * @throws \Exception
     */
    public function saveProductsPermission(Request\DataSet $request, Response $response){
        try {
            $row = $request->getDataSet()->getRows()[0];
            $licenseInfo = $row['LICENSE_INFO'];
            $licenseInfo = json_decode(LibUtilities::zeedhiDecrypt($licenseInfo), true);
            $this->loginService->saveProductsPermission($licenseInfo);
        } catch(\Exception $e) {
            $response->setError(new Response\Error($e->getMessage(), Response\Message::TYPE_ERROR));
        }
    }

    /**
     * @param Request\Filter $request
     * @param Response $response
     * @throws \Exception
     */
    public function saveVariableMeasure(Request\DataSet $request, Response $response){
        try {
            $row = $request->getDataSet()->getRows()[0];
            $licenseInfo = $row['LICENSE_INFO'];
            $licenseInfo = json_decode(LibUtilities::zeedhiDecrypt($licenseInfo), true);
            $variableMeasure = $generalCollection = array();

            if(!empty($licenseInfo['VARIABLE_MEASURE'])) {
                $variableMeasure = $this->loginService->getVariableMeasureRegisters($licenseInfo);
            }

            if(!empty($licenseInfo['GENERAL_COLLECTION'])) {
                $generalCollection = $this->loginService->getGeneralCollectionRegisters($licenseInfo);
            }

            if(!empty($variableMeasure) || !empty($generalCollection)) {
                $this->loginService->saveVariableMeasure($variableMeasure, $generalCollection, $licenseInfo);
            }
        } catch(\Exception $e) {
            $response->setError(new Response\Error($e->getMessage(), Response\Message::TYPE_ERROR));
        }
    }

    /**
     * @param Request\Filter $request
     * @param Response $response
     * @throws \Exception
     */
    public function setLogAccess(Request\DataSet $request, Response $response){
        try {
            $this->loginService->setLogAccess();
        } catch(\Exception $e) {
            $response->setError(new Response\Error($e->getMessage(), Response\Message::TYPE_ERROR));
        }
    }
}