<?php

use PhpAmqpLib\Message\AMQPMessage;

require_once __DIR__ . '/../../../../vendor/autoload.php';
require_once 'Zend/Loader/Autoloader.php';

$loader = Zend_Loader_Autoloader::getInstance();

require_once __DIR__ . '/../RpcServerBase.php';
require_once __DIR__ . "../../../APIs/Log.php";
require_once __DIR__ . "../../../APIs/VSD/Vistoria.php";
require_once __DIR__ . "../../../Db/Table/Abstract.php";
require_once __DIR__ . "../../../DocuSign/Base.php";


class Agro_RabbitMQ_VSD_RpcServer extends Agro_Rabbitmq_RpcServerBase
{
    private $config = null;
    private $curl_options = null;
    public $postArray =  null;
    public $host = null;
    public $proto = null;
    public $url = null;
    public $client = null;
    public $header = null;
    public $response = null;
    public $result = null;

    public function __construct(string $func, string $env, string $nomeFila)
    {
        parent::__construct($func, $env);
        $this->nomeFila = $nomeFila;
        
    }

    public function process(AMQPMessage $msg) {
        echo "[SERVER] - process: begin\n";

        $payload = json_decode($msg->getBody(), true);
       
        $this->{$this->func}($payload);

        $msg->get('channel')->basic_ack(
            $msg->get('delivery_tag')
        );
        echo "[SERVER] - process: end\n";
    }

    public function run($params)
    {
        echo "[SERVER] - run: begin\n";
        try {
            if (!array_key_exists('acao', $params)) {
                throw new Exception("Ação não informada.");
            }

            switch ($params['acao']) {
                case 'gerarNovaVistoria':
                    $this->gerarNovaVistoria($params);
                    break;
    
                case 'enviarTermoAutorizacao':
                    $this->enviarTermoAutorizacao($params);
                    break;

                case 'gerarLaudoFinal':
                    $this->gerarLaudoFinal($params);
                    break;
                    
                case 'enviarLaudoFinal':
                    $this->enviarLaudoFinal($params);
                    break;
                
                default:
                    throw new Exception("Ação não encontrada.");
                    break;
            }

            echo "[SERVER] - run: end\n";
        } catch (\Throwable $th) {
            echo "[SERVER] - run: error\n";
            echo "[SERVER] - {$th->getMessage()}\n";
        }

    }

    public function gerarLaudoFinal($params)
    {
        echo "[SERVER] - gerarLaudoFinal: begin\n";
        echo "[SERVER] - gerarLaudoFinal: params " . json_encode($params) . "\n";

        $this->curl('/sinistro2/Laudofinal/gerarlaudofinal', $params);

        echo "[SERVER] - gerarLaudoFinal: end\n";
    }

    public function enviarLaudoFinal($params)
    {
        echo "[SERVER] - enviarLaudoFinal: begin\n";
        echo "[SERVER] - enviarLaudoFinal: params " . json_encode($params) . "\n";

        $this->curl('/sinistro2/Laudofinal/enviarlaudofinal', $params);

        echo "[SERVER] - enviarLaudoFinal: end\n";
    }

    public function gerarNovaVistoria($params)
    {
        echo "[SERVER] - gerarNovaVistoria: begin\n";
        echo "[SERVER] - gerarNovaVistoria: params " . json_encode($params) . "\n";
        try {
            $porta = (
                array_key_exists(
                    'resources.db.params.port',$this->settings[$this->env]
                )?
                $this->settings[$this->env]['resources.db.params.port']
                :'5432'
            );

            $conexao = [
                'host' => $this->settings[$this->env]['resources.db.params.host'],
                'port' => $porta,
                'dbname' => $this->settings[$this->env]['resources.db.params.dbname'],
                'username' => $this->settings[$this->env]['resources.db.params.username'],
                'password' => $this->settings[$this->env]['resources.db.params.password'],
            ];

            $adapter = Zend_Db::factory('PDO_PGSQL', $conexao);
            Zend_Db_Table_Abstract::setDefaultAdapter($adapter);
            $db = Zend_Db_Table::getDefaultAdapter();

            $db->beginTransaction();

            if (empty($params['id_vistoria'])) {
                throw new Exception("Id da vistoria não informado.");
            }

            if (!filter_var($params['id_vistoria'], FILTER_VALIDATE_INT)) {
                throw new Exception("Id da vistoria inválido.");
            }

            if (empty($params['id_usuario'])) {
                throw new Exception("Id do usuário não informado.");
            }

            if (!filter_var($params['id_usuario'], FILTER_VALIDATE_INT)) {
                throw new Exception("Id do usuário inválido.");
            }
    
            $vistoria = ['id_vistoria' => $params['id_vistoria']];
            $usuario = ['id' => $params['id_usuario']];

            $vistoriaVSD = new Agro_APIs_VSD_Vistoria();
            $vistoriaVSD->novaVistoria($vistoria, $usuario, $db);
            $db->commit();
            echo "[SERVER] - gerarNovaVistoria: end\n";
        } catch (\Throwable $th) {
            echo "[SERVER] - gerarNovaVistoria: error\n";
            $env = strpos($this->env, 'docker') !== false ? 'docker' : 'production'; 

            $db->rollback();
            $agroLog = new Agro_Log(Agro_Log::VSD, false, $env);
            $agroLog->setParams($params);
            $agroLog->setRota('gerarNovaVistoria');
            $agroLog->logError("Erro: " . $th->getMessage() . "\n");
        }
    }

    public function enviarTermoAutorizacao($params)
    {
        echo "[SERVER] - enviarTermoAutorizacao: begin\n";
        echo "[SERVER] - enviarTermoAutorizacao: params " . json_encode($params) . "\n";
        
        if (!empty($params['id_laudo_final'])
            && filter_var($params['id_laudo_final'], FILTER_VALIDATE_INT)
            && $this->possuiLaudoFilaEspera((int) $params['id_laudo_final'])) {

            $this->curl('/regulacao/lf034/enviardocusign', $params);
        }
            
        echo "[SERVER] - enviarTermoAutorizacao: end\n";
    }

    private function curl(string $url, array $params): void
    {
        $this->initCurl();
        $this->url .= $url;
        $this->doRequest('POST', $params);
    }

    private function initCurl()
    {
        $this->host = 'agronet.local';
        $this->proto = 'http';

        preg_match("/^agrobr-app02\.*/", gethostname(), $matches);

        if (count($matches) > 0) {
            $this->host = 'agronet.agrobrasilseguros.com.br';
            $this->proto = 'https';
        }

        $this->curl_options = array(
        		'CURLOPT_FOLLOWLOCATION' => true,
        		'CURLOPT_SSL_VERIFYPEER' => true,
        );

        $this->config = array(
            'adapter'      => 'Zend_Http_Client_Adapter_Curl',
            'ssltransport' => 'tls',
            'strict'       => false,
            'persistent'   => true,
            'curloption'   => $this->curl_options
        );

        $this->url = $this->proto.'://'.$this->host;

        $this->client = new Zend_Http_Client($this->url . '/login', $this->config);

        $this->postArray = [
            'usuario' => $this->settings[$this->env]['constants.CURL_USER'],
            'senha' => $this->settings[$this->env]['constants.CURL_PASSWORD']
        ];
        $this->client->setParameterPost($this->postArray);
        $this->setHeader($this->host, $this->proto);
        $this->client->setHeaders($this->getHeader());

        $this->client->setCookie('PHPSESSID', str_shuffle('agrobrasil'.rand().'seguros'));

        $this->response = $this->client->request('POST');
        $this->setResult($this->response);

        // zerando o array POST do client para não ter que fazer isso toda vez que for utilizar a classe
        // visto que ele é setado na linha 55 com usuário e senha
        // caso haja necessidade de setar novamente, usar os métodos set e get da variável $postArray
        $this->client->setParameterPost(array());
    }

    // adiciona host e protocolo ao header do objeto cliente
    public function setHeader($host, $proto) {
        $this->header = array(
            'Host: '.$host,
            'User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0',
            'Accept: text/javascript, application/javascript, */*',
            'Accept-Language: en-gb,en;q=5.0',
            'Accept-Encoding: gzip, deflate',
            'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
            'X-Requested-With: XMLHttpRequest',
            'Referer: '.$proto.'://'.$host
        );
    }

    // retorna o header configurado
    public function getHeader() {
        return $this->header;
    }

    // transforma a saída visível para o objeto Http_Response
    public function setResult($valor) {
        $this->result = json_decode($valor->getBody());
    }

    public function doRequest($tipo='POST',$post=null) {
        $this->response = null;
        $this->result = null;
       	$this->client->setParameterPost($post);
        try {
            $this->client->setUri($this->url);
        } catch (Exception $e) {
            print('Erro de URL. Geralmente é um defeito que vem dos arquivos editados no windows. Cria o mesmo arquivo no VIM.');
        }
        $this->setHeader($this->host, $this->proto);
        $this->client->setHeaders($this->getHeader());
        $this->client->setMethod($tipo);
        $this->response = $this->client->request();
        $this->result = $this->response;
    }

    
    /**
     * Valida se o Laudo Final informado está na fila para ser enviado
     *
     * @param int $idLaudoFinal
     * @return bool
     */
    private function possuiLaudoFilaEspera(int $idLaudoFinal): bool
    {
        $statment = $this->pdo->prepare("
            SELECT 1
              FROM sinistro.laudos_finais_docusign lfd
             WHERE lfd.id_laudo_final = :id_laudo_final
               AND lfd.ds_status = :ds_status
               AND lfd.fl_ativo is true
        ");

        $statment->execute(['id_laudo_final' => $idLaudoFinal, 'ds_status' => Agro_DocuSign_Base::STATUS_WAITING]);
        $result = $statment->fetchObject();
        return !empty($result);
    }
}
