<?php

namespace Teknisa\Libs\Util;

use Doctrine\DBAL\Connection;
use Zeedhi\Framework\DBAL\DriverManager;
use Zeedhi\Framework\Session\Session;
use Zeedhi\Framework\DependencyInjection\InstanceManager;

class ConnectionFactory extends \Zeedhi\Framework\ORM\ConnectionFactory {

    public static function updateConnectionParams(array $connectionParams, $config = null, $eventManager = null, Session $session = null){
        $nrOrg = false;
        if($session) {
            $nrOrg = $session->has('nrorg') ? $session->get('nrorg') : $session->get('NRORG');
            if(empty($nrOrg)) {
                try {
                    self::checkAccessAndSetSession($session);
                } catch(\Exception $e) {}
                $nrOrg = $session->has('nrorg') ? $session->get('nrorg') : $session->get('NRORG');
            }
            self::setCurrentDBName($connectionParams, $session);
        }

        if ($nrOrg && isset($connectionParams['useVpd']) && $connectionParams['useVpd'] == 'true') {
            $connectionParams = self::factoryVPDConnectionParams($connectionParams, $nrOrg);
        }

        if(empty($connectionParams["password"])) {
            $connectionParams["password"] = '';
        } else if(isset($connectionParams["isEncrypted"]) && $connectionParams["isEncrypted"] == 'true') {
            $cryptKey = isset($connectionParams["cryptKey"]) ? $connectionParams["cryptKey"] : null;
            $connectionParams["password"] = Utilities::zeedhiDecrypt($connectionParams["password"], $cryptKey);
            $connectionParams["isEncrypted"] = false;
        }
        if (!empty($connectionParams['platform']) && is_string($connectionParams['platform'])) {
            $platform = InstanceManager::getInstance()->getService($connectionParams['platform']);
            if($platform) {
                $connectionParams['platform'] = $platform;
            }
        }
        $connection = DriverManager::getConnection($connectionParams, $config, $eventManager);
        self::insertSQLWebTunning($connection, $session);
        return $connection;
    }

    protected static function setCurrentDBName($connectionParams, $session) {
        //Set current DBNAME in session for use in login session
        if(isset($connectionParams['sessionMode'])) {
            $encryptedDBName = Utilities::zeedhiEncrypt($connectionParams['dbname']);
            $session->set('CURRENT_DBNAME', preg_replace('/[^A-Za-z0-9\-]/', '', $encryptedDBName));
        } else {
            $encryptedUser = Utilities::zeedhiEncrypt($connectionParams['user']);
            $session->set('CURRENT_DBNAME', preg_replace('/[^A-Za-z0-9\-]/', '',$encryptedUser));
        }
    }

    protected static function factoryVPDConnectionParams($connectionParams, $nrOrg) {
        if (isset($connectionParams['vpdWithWallet']) && $connectionParams['vpdWithWallet'] == 'true') {
            $connectionParams['user']        = '/';
            $connectionParams['password']    = '';
            $connectionParams['dbname']      = 'USR_ORG_' . $nrOrg;
            $connectionParams['sessionMode'] = -2147483648;

            unset($connectionParams['host']);
            unset($connectionParams['port']);
        } else {
            $connectionParams['user'] = 'USR_ORG_' . $nrOrg;
            if (!empty($connectionParams['vpdPassword'])) {
                $connectionParams['password'] = $connectionParams['vpdPassword'];
            }
            if (empty($connectionParams['host'])) {
                $connectionParams['dbname'] = 'USR_ORG_' . $nrOrg;
            }
            if (isset($connectionParams['isWallet']) && $connectionParams['isWallet'] == 'true') {
                $connectionParams['dbname']  = $connectionParams['vpdDBNAME'];
                $connectionParams['host']    = $connectionParams['vpdHost'];
                $connectionParams['port']    = $connectionParams['vpdPort'];
                $connectionParams['service'] = $connectionParams['vpdService'];
                unset($connectionParams['sessionMode']);
            }
        }
        return $connectionParams;
    }

    /**
     * @param Connection $connection
     * @param Session $session
     * @throws \Exception
     */
    public static function insertSQLWebTunning($connection, $session) {
        $kernel = InstanceManager::getInstance()->getService('kernel');
        if(method_exists($kernel, 'setIsCriticalError')) {
            $kernel->setIsCriticalError(false);
        }
        try {
            if(Utilities::getUseSQLWebTunningParameter()) {
                $query = "INSERT INTO SQLWEBTUNNING (DSREMOTEADDR, DSREMOTEHOST, DSREMOTEAPPL, DSSERVERRDM,
                                                     DSSERVERDLL,  DTSTARTDATE,  DSREMOTEOPER, DSSERVMETHOD)
                               VALUES (:DSREMOTEADDR, :DSREMOTEHOST, :DSREMOTEAPPL, :DSSERVERRDM,
                                       :DSSERVERDLL,  SYSDATE,       :DSREMOTEOPER, :DSSERVMETHOD)";

				if(isset($_SERVER['HTTP_HOST'])) {
					$host = $_SERVER['HTTP_HOST'];
				} else if(isset($_SERVER['SERVER_NAME'])) {
					$host = $_SERVER['SERVER_NAME'];
				} else {
                    $host = '111.111.111.111';
                }                
				if(isset($_SERVER['REQUEST_URI'])) {
					$requestUri = explode('index.php', trim($_SERVER['REQUEST_URI']));
                    $route      = array_pop($requestUri);
				} else {
					$route = 'EMPTY_ROUTE';
				}
				
                $cdoperador = $session && $session->has('CDOPERADOR') ? $session->get('CDOPERADOR') : 'SESSAO_N_INI';
                $hostArr    = explode('.', $host);
                $hostInit   = array_shift($hostArr);
                $remoteAddr = trim(substr(gethostbyname($host), 0, 15));
                if(strpos($remoteAddr, ':') !== false) {
                    $remoteAddr = explode(':', $remoteAddr)[0];
                }

                $params = array (
                    'DSREMOTEADDR' => $remoteAddr,
                    'DSREMOTEHOST' => trim(substr($hostInit, 0, 15)),
                    'DSREMOTEAPPL' => strval(Utilities::getProjectIdParameter()),
                    'DSSERVERRDM'  => trim(substr(implode('.', $hostArr), 0, 20)),
                    'DSSERVERDLL'  => 'ZEEDHI_REQUEST',
                    'DSREMOTEOPER' => trim(substr($cdoperador, 0, 12)),
                    'DSSERVMETHOD' => substr($route, 0, 30)
                );
                $connection->executeQuery($query, $params);
            }
        } catch(\Exception $e) {
            error_log('SQLWEBTUNNING error: ' . $e->getMessage());
        }
        
        if(method_exists($kernel, 'setIsCriticalError')) {
            $kernel->setIsCriticalError(true);
        }
    }

    private static function checkAccessAndSetSession($session) {
        $httpKernel = InstanceManager::getInstance()->getService('kernel');
        $oauth      = InstanceManager::getInstance()->getService('oAuthImpl');

        $token = $httpKernel->getHttpRequest()->getHeaders()->get(RequestListenerOAuth::OAUTH_HEADER);
        if(!empty($token)) {
            $secretId = $httpKernel->getHttpRequest()->getHeaders()->get(RequestListenerOAuth::OAUTH_SECRET_ID);
            $keepConn = $httpKernel->getHttpRequest()->getHeaders()->get(RequestListenerOAuth::OAUTH_KEEP_CONNECTED);
            $keepConn = $keepConn == RequestListenerOAuth::KEEP_CONNECTED_POSITIVE ? true : false;
            $access   = $oauth->checkAccess($token, $secretId, array(), $keepConn);

            if (!empty($access)) {
                if($session->getId() != $access['sessionId']) {
                    $session->start();
                    $session->destroy();
                    $session->setId($access['sessionId']);
                }
                $session->start();
            }
        }
    }
}