<?php

use DocuSign\eSign\Model\RecipientAdditionalNotification;
use DocuSign\eSign\Model\RecipientPhoneNumber;

class Sinistro2_Model_LaudosFinaisDocusign extends Agro_DocuSign_Base
{
    protected $_log = true;
    protected $_schema = 'sinistro';
    protected $_name = 'laudos_finais_docusign';
    protected $_primary = 'id';

    const ROLE_NAME_SEGURADO = 'Segurado';

    /**
     * Busca o vínculo do laudo final com a docusign (id_envelope)
     * @param int $idLaudoFinal
     * @return Zend_Db_Table_Row
     */
    public function getByLaudoFinal($idLaudoFinal, $somenteAtivo = true)
    {
        $select = $this->select()->setIntegrityCheck(false);
        $select->from(array('lfd' => 'sinistro.laudos_finais_docusign'), '*');
        $select->join(array('u' => 'sistema.usuarios'), 'lfd.id_usuario_criacao = u.id', 'ds_nome_usuario');
        $select->where("lfd.id_laudo_final={$idLaudoFinal}");

        if ($somenteAtivo) {
            $select->where("lfd.fl_ativo is true");
        }

        $select->order('lfd.id DESC');

        return $this->fetchAll($select)->toArray();
    }

    /**
     * Desativa todos os registros anteriores do laudo final informado e inclui um novo ativo.
     *
     * @param mixed $data [
     *  'id_laudo_final' => '',
     *  'id_envelope' => '',
     *  'ds_status' => '',
     *  'ds_mensagem' => ''
     * ]
     * @return int
     */
    public function save($data): int
    {
        $this->update(array('fl_ativo' => 'f'), "id_laudo_final = " . $data['id_laudo_final']);

        $Row = $this->createRow();
        $Row->id_laudo_final = $data['id_laudo_final'];
        $Row->id_envelope = $data['id_envelope'];
        $Row->ds_status = $data['ds_status'];
        $Row->ds_mensagem = $data['ds_mensagem'];
        $Row->save();

        return $Row->id;
    }

    /**
     * Deleta todos os registros de um laudo final
     *
     * @param int $idLaudoFinal
     */
    public function deleteByLaudoFinal($idLaudoFinal): void
    {
        parent::delete($idLaudoFinal, 'id_laudo_final');
    }

    /**
     * Adiciona o laudo final informado no parâmetro a fila de envio para a docusign com o status de 'waiting'.
     * Caso não tenha AT agendado para o processamento da fila de envios (verifica se tem at especificado com a letra 'd'), cria um novo AT.
     *
     * @param int $idLaudoFinal
     * @param string $tipoEnvio
     */
    public function adicionarFila(int $idLaudoFinal): void
    {
        $data = [
            'id_laudo_final' => $idLaudoFinal,
            'id_envelope' => '',
            'ds_status' => Agro_DocuSign_Base::STATUS_WAITING,
        ];
        $retorno = $this->save($data);

        if (empty($retorno)) {
            throw new Exception("Erro ao adicionar o laudo final na lista de envio.");
        }

        if (!Agro_Util::hasAtByLetter('d')) {
            //@TODO verificar se reaproveito ou faço um novo; troco a letra ou não...
            Agro_Util::generateAtscript("processarfiladocusign.php", array(), '', 'd');
        }
    }

    /**
     * Busca os registros ativos com os status informados no parâmetro
     *
     * @param string[] $status
     * @return array
     */
    public function getFila(array $status): array
    {
        $whereStatus = [];
        foreach ($status as $dsStatus) {
            $whereStatus[] = "'{$dsStatus}'";
        }

        $select = $this->select()->setIntegrityCheck(false);
        $select->from(array('lfd' => 'sinistro.laudos_finais_docusign'), '*');
        $select->where("lfd.fl_ativo is true");
        $select->where("lfd.ds_status in (" . implode(', ', $whereStatus) . ")");
        $select->order('lfd.id');

        return $this->fetchAll($select)->toArray();
    }

    /**
     * Verifica se houve alteração do status na docusign e cria um novo registro caso haja.
     * Retorna o atual status que o envelope está na docusign.
     *
     * @param mixed $laudoFinalDocusign [
     *  'id_laudo_final' => '',
     *  'id_envelope' => '',
     *  'ds_status' => '',
     *  'ds_mensagem' => ''
     * ]
     * @return string
     */
    public function atualizarStatusEnvelope(array $laudoFinalDocusign): string
    {
        $dadosEnvelope = $this->buscarStatusEnvelope($laudoFinalDocusign['id_envelope'], $laudoFinalDocusign['ds_status']);

        if ($dadosEnvelope['ds_status'] != $laudoFinalDocusign['ds_status']) {
            
            $laudoFinalDocusign['ds_status'] = $dadosEnvelope['ds_status'];
            $laudoFinalDocusign['ds_mensagem'] = $dadosEnvelope['ds_mensagem'];
            $this->save($laudoFinalDocusign);
        }

        return $laudoFinalDocusign['ds_status'];
    }

    /**
     * Busca todos os documentos de um envelope da docusign pelo laudo final informado
     *
     * @param int $idLaudoFinal
     * @return SplFileObject[]|array
     */
    public function getDocumentoByLaudoFinal(int $idLaudoFinal): array
    {
        $laudoFinalDocusign = $this->getByLaudoFinal($idLaudoFinal);

        if (empty($laudoFinalDocusign)) {
            throw new Exception("Nenhum envio encontrado para o laudo final informado.");
        }
        
        if (empty($laudoFinalDocusign[0]['id_envelope'])) {
            throw new Exception("Nenhum envelope encontrado para o laudo final informado.");
        }

        $emailCompositeTemplates = new Agro_DocuSign_EmailCompositeTemplates();
        $idEnvelope = $laudoFinalDocusign[0]['id_envelope'];
        $documentos = $emailCompositeTemplates->getAllDocumentos($idEnvelope);

        if (empty($documentos)) {
            throw new Exception("Nenhum documento encontrado para o laudo final informado.");
        }

        return $documentos;
    }

    /**
     * Envia ou reenvia (caso já haja envelope informado) o termo de autorização do acompanhante do laudo final
     *
     * @param int $idLaudoFinal
     */
    public function enviarTermoAutorizacaoAcompanhante(int $idLaudoFinal): void
    {
        $validaDadosEnvio = new Sinistro2_Service_ValidaDadosEnvio();
		$dadosEnvio = $validaDadosEnvio->executa($idLaudoFinal, Sinistro2_Service_ValidaDadosEnvio::TIPO_ENVIO_DOC_ACOMPANHANTE);

        // Caso já existe envelope para o laudo final, só reenviamos
        $idEnvelope = $this->reenviarEnvelope($idLaudoFinal, $dadosEnvio);

        //Caso não exista o idEnvelope, criamos um novo envelope
        if (empty($idEnvelope)) {
           $idEnvelope = $this->enviarEnvelope($dadosEnvio);
        }

        $data['id_laudo_final'] = $dadosEnvio['id_laudo_final'];
        $data['id_envelope'] = $idEnvelope;
        $data['ds_status'] = Seguro_Model_PropostasDocusign::STATUS_SENT;
        $this->save($data);
    }

    /**
     * Cria um novo envelope o envia
     *
     * @param array $dadosAssinatura [
     *      'ds_telefone_segurado' = '',
     *      'ds_email_segurado' = '',
     *      'ds_nome_proponente' = '',
     * ]
     * @return string $idEnvelope
     */
    private function enviarEnvelope(array $dadosAssinatura): string
    {
        $tipoAssinatura = Agro_DocuSign_EmailCompositeTemplates::TIPO_ASSINATURA_EMAIL;
        if ($dadosAssinatura['ds_tipo_envio'] == 'WHATS') {
            $tipoAssinatura = Agro_DocuSign_EmailCompositeTemplates::TIPO_ASSINATURA_SMS;
        }

        $emailCompositeTemplates = new Agro_DocuSign_EmailCompositeTemplates();
        $emailCompositeTemplates->setTipoAssinatura($tipoAssinatura);
        
        $this->addTemplateTermoAutorizacaoAcompanhante($emailCompositeTemplates, $dadosAssinatura);

        $emailCompositeTemplates->setEmailSubject("Termo de autorização de acompanhante");
        $emailCompositeTemplates->setEmailBlurb("Prezado(a),

        Você está recebendo o link para assinatura do termo de autorização do acompanhante. Para acessar o documento, clique em 'Analisar documento'.
        Em caso de dúvidas entrar em contato com: [contato]
        
        Grato,");
        $emailCompositeTemplates->setBrandId("da32bc40-3fc3-4f8d-8b72-75944543fcea");
        return $emailCompositeTemplates->enviar(true);
    }

    /**
     * Valida se já existe um envelope para o laudo final informado.
     * Caso haja envelope, verifica se o e-mail do signatário mudou e o altera no envelope senão apenas reenvia o envelope.
     *
     * @param int $idLaudoFinal
     * @param array $dadosAssinatura [
     *      'ds_telefone_segurado' = '',
     *      'ds_email_segurado' = '',
     *      'ds_nome_proponente' = '',
     * ]
     * @return string|null $idEnvelope
     */
    private function reenviarEnvelope(int $idLaudoFinal, array $dadosAssinatura):? string
    {
        $laudoFinalDocusign = $this->getByLaudoFinal($idLaudoFinal);
        if (!empty($laudoFinalDocusign[0]) && !empty($laudoFinalDocusign[0]['id_envelope'])) {
            
            $statusAtual = $this->buscarStatusEnvelope($laudoFinalDocusign[0]['id_envelope'], $laudoFinalDocusign[0]['ds_status']);

            $statusValidos = [
                Agro_DocuSign_Base::STATUS_ERROR,
                Agro_DocuSign_Base::STATUS_SENT,
                Agro_DocuSign_Base::STATUS_DELIVERED,
            ];
            
            if (!in_array($statusAtual['ds_status'], $statusValidos)) {
                throw new Exception("Não é possível reenviar o termo em seu status de envio atual.");
            }

            $emailCompositeTemplates = new Agro_DocuSign_EmailCompositeTemplates();
            $envelope = $emailCompositeTemplates->getEnvelope($laudoFinalDocusign[0]['id_envelope']);
            if (empty($envelope)) {
                throw new Exception("Não foi possível encontrar o envelope {$laudoFinalDocusign[0]['id_envelope']}.");
            }
    
            $signerAlterado = [];
            foreach ($envelope->getRecipients()->getSigners() as $signer) {
                if ($signer->getRecipientId() == 1) {

                    if ($dadosAssinatura['ds_tipo_envio'] == 'WHATS' && $signer->getPhoneNumber() != $dadosAssinatura['ds_telefone_segurado']) {

                        $numeroCelularAnterior = null;
                        $numeroCelularAtual = preg_replace('([^0-9])', '', $dadosAssinatura['ds_telefone_segurado']);
                        $phoneNumber = $signer->getPhoneNumber();
                        
                        if (!empty($phoneNumber)) {
                            $numeroCelularAnterior = $phoneNumber->getNumber();
                        }

                        if ($numeroCelularAnterior != $numeroCelularAtual) {
                            
                            $smsDelivery = new RecipientAdditionalNotification();
                            $smsDelivery->setSecondaryDeliveryMethod("SMS");
                            
                            $signerPhone = new RecipientPhoneNumber([
                                'country_code' => '55',
                                'number' => $numeroCelularAtual
                            ]);
                            
                            $smsDelivery->setPhoneNumber($signerPhone);
                            
                            $signer->setEmail('');
                            $signer->setPhoneNumber($signerPhone);
                            $signer->setDeliveryMethod('sms');
                            $signerAlterado[] = $signer;
                        }

                    } elseif ($dadosAssinatura['ds_tipo_envio'] == 'EMAIL' && $signer->getEmail() != $dadosAssinatura['ds_email_segurado']) {
                        $signer->setPhoneNumber('');
                        $signer->setEmail($dadosAssinatura['ds_email_segurado']);
                        $signer->setDeliveryMethod('email');
                        $signerAlterado[] = $signer;
                    }
                }
            }

            if (!empty($signerAlterado)) {
                $emailCompositeTemplates->alterarSignatario($laudoFinalDocusign[0]['id_envelope'], $signerAlterado);
            } else {
                $emailCompositeTemplates->reenviar($laudoFinalDocusign[0]['id_envelope']);
            }

            return $laudoFinalDocusign[0]['id_envelope'];
        }

        return null;
    }

    /**
     * Adiciona o template do termo de autorização do acompanhante.
     *
     * @param Agro_DocuSign_EmailCompositeTemplates $emailCompositeTemplates
     * @param mixed[] $dadosAssinatura [
     *  'id_laudo_final' => '',
     *  'ds_nome_proponente' => '',
     *  'ds_email_segurado' => '',
     * ]
     */
    private function addTemplateTermoAutorizacaoAcompanhante(Agro_DocuSign_EmailCompositeTemplates &$emailCompositeTemplates, $dadosAssinatura): void
    {
        $data = new stdClass();
        $data->tipo = Agro_DocuSign_EmailCompositeTemplates::TIPO_TEMPLATE;
        $data->tipoTemplate = Agro_DocuSign_TemplateFactory::TERMO_AUTORIZACAO_ACOMPANHANTE;
        $data->parametros = ['id_laudo_final' => $dadosAssinatura['id_laudo_final']];
        $data->signers = array();

        $data->signers[] = (object) [
            'name' => $dadosAssinatura['ds_nome_proponente'],
            'email' => $dadosAssinatura['ds_email_segurado'],
            'number' => $dadosAssinatura['ds_telefone_segurado'],
            'roleName' => self::ROLE_NAME_SEGURADO,
        ];

        $emailCompositeTemplates->add($data);
    }
}
