<?php declare(strict_types=1);

class Sinistro2_Service_SalvarLiquidacaoPagamentoAdicional
{
    const USUARIOS_PERMISSAO_EDICAO = ['tatiana.tondim', 'marcia.correa', 'tiago.zschornack'];

    private $usuario;

    public function executar(array $dados): Zend_Db_Table_Row
    {
        $this->usuario = Zend_Auth::getInstance()->getIdentity();
        $modelLiquidacaoPagamentoAdicional = new Sinistro2_Model_LiquidacaoPagamentoAdicional();
        $modelStatus = new Sistema_Model_Status();
        
        if (!array_key_exists('idLiquidacao', $dados) || !filter_var($dados['idLiquidacao'], FILTER_VALIDATE_INT)) {
            throw new Exception('ID Liquidação inválido.');
        }

        $idLiquidacao = (int) $dados['idLiquidacao'];
        $pagamentoAdicional = $modelLiquidacaoPagamentoAdicional->getPagamentoAdicional($idLiquidacao);
        
        $isEdicao = !empty($pagamentoAdicional);

        $this->validarDados($dados, $isEdicao);
        $this->validarPermissao($pagamentoAdicional);

        $valorTotalIndenizadoAnteriormente = (new Sinistro2_Model_Liquidacoes())
            ->getValorTotalIndenizacao($idLiquidacao);

        if ($dados['valorTotalCorrigido'] <= $valorTotalIndenizadoAnteriormente) {
            throw new Exception('O valor total corrigido deve ser superior à indenização total paga.');
        }

        $dadosLiquidacao = (new Sinistro2_Model_Liquidacoes())->getLiquidacao($idLiquidacao);

        if ($dados['valorTotalCorrigido'] > $dadosLiquidacao['vl_lmga_total']) {
            throw new Exception('O valor total corrigido não pode ser maior que o valor LMGA total.');
        }
        
        $enviarEmailAguardandoRevisao = false;
        
        if (!$isEdicao) {
            if ($dados['valorTotalCorrigido'] - $valorTotalIndenizadoAnteriormente > 20000) {
                $enviarEmailAguardandoRevisao = true;
                $idStatus = $modelStatus->getId(
                    'AGUARDANDO_REVISAO',
                    'LIQUIDACAO_PAGAMENTO_ADICIONAL'
                );
            } else {
                $idStatus = $modelStatus->getId(
                    'PENDENTE_PAGAMENTO',
                    'LIQUIDACAO_PAGAMENTO_ADICIONAL'
                );
            }
        } else {
            $idStatus = $dados['idStatus'];
        }

        $nomeArquivoAntigo = $pagamentoAdicional != null
            ? $pagamentoAdicional->ds_nome_arquivo
            : '';

        $dados = [
            'id_liquidacao' => $idLiquidacao,
            'vl_indenizacao_paga' => $valorTotalIndenizadoAnteriormente,
            'vl_total_corrigido' => $dados['valorTotalCorrigido'],
            'ds_observacao' => $dados['observacoes'],
            'id_status' => $idStatus,
            'ds_nome_arquivo' => $nomeArquivoAntigo
        ];
        
        $row = $modelLiquidacaoPagamentoAdicional->salvar($dados);

        if (!$row) {
            throw new Exception('Erro ao salvar pagamento adicional.');
        }

        $liquidacao = (new Sinistro2_Model_Liquidacoes())->find($idLiquidacao)->current();

        $valorTotalCorrigidoFormatado = 'R$ '. Agro_Util::formatDbCurrency($dados['vl_total_corrigido']);
        $valorIndenizacaoPaganAnteriormenteFormatado = 'R$ '. Agro_Util::formatDbCurrency($valorTotalIndenizadoAnteriormente);
        
        $diferenca = 'R$ '. Agro_Util::formatDbCurrency($dados['vl_total_corrigido'] - $valorTotalIndenizadoAnteriormente);
        $observacaoArquivo = "Diferença Indenização: {$dados['ds_observacao']}<br>Valor da indenização paga anteriormente: {$valorIndenizacaoPaganAnteriormenteFormatado}";
        $observacaoArquivo .= "<br>Valor total corrigido: {$valorTotalCorrigidoFormatado}<br>Valor Pagamento Adicional: {$diferenca}";
        
        $nomeArquivo = $this->salvarArquivo(
            $liquidacao->id_processo,
            $idLiquidacao,
            $isEdicao,
            $nomeArquivoAntigo,
            $observacaoArquivo
        );
		
        if (!empty($nomeArquivo)) {
            $row->ds_nome_arquivo = $nomeArquivo;

            if ($isEdicao) {
                unlink(APPLICATION_PATH . "upload_files/sinistro_processo/{$nomeArquivoAntigo}");
            }
        }

        if ($enviarEmailAguardandoRevisao) {
            $this->enviarEmailAguardandoRevisao($liquidacao->id_processo);
        }

        return $row;
    }

    private function validarPermissao(?Zend_Db_Table_Row $pagamentoAdicional): void {
        if ($this->usuario->id_empresa != Sistema_Model_Empresas::AGROBRASIL) {
            throw new Exception('Usuário sem permissão para incluir/editar.');
        }
        
        /**
         * Apenas usuarios definidos em Sinistro2_Model_LiquidacaoPagamentoAdicional::USUARIOS_PERMISSAO_EDICAO_EXCLUSAO tem permissão para alterar
         * pagamento adicional quando status estiver em AGUARDANDO_REVISAO
         */
        $idStatusAguardandoRevisao = (new Sistema_Model_Status())->getId(
            'AGUARDANDO_REVISAO',
            'LIQUIDACAO_PAGAMENTO_ADICIONAL'
        );

        if (!empty($idUsuarioResponsavelCriacao)) {
            $idUsuarioResponsavelCriacao = (new Sinistro2_Model_LiquidacaoPagamentoAdicional())
                ->getIdUsuarioResponsavelCriacao($pagamentoAdicional->id_liquidacao);
        }

        if (
            !empty($pagamentoAdicional)
            && $this->usuario->ds_chave !== 'ADMIN'
            && !in_array($this->usuario->ds_nome_usuario, Sinistro2_Model_LiquidacaoPagamentoAdicional::USUARIOS_PERMISSAO_EDICAO_EXCLUSAO)
            && $this->usuario->id != $idUsuarioResponsavelCriacao
            && $pagamentoAdicional->id_status == $idStatusAguardandoRevisao
        ) {
            throw new Exception('Usuário sem permissão para editar.');
        }
    }

    private function validarDados(array $dados, bool $isEdicao): void
    {
        if (empty($dados['observacoes'])) {
            throw new Exception('Campo Observações não informado.');
        }

        if (empty($dados['valorTotalCorrigido'])) {
            throw new Exception('Valor total corrigido não informado.');
        }
        
        if (!filter_var($dados['valorTotalCorrigido'], FILTER_VALIDATE_FLOAT)) {
            throw new Exception('Valor total corrigido inválido.');
        }

        if (empty($_FILES) && !$isEdicao) {
            throw new Exception('Nenhum arquivo anexado.');
        }
    }

    private function salvarArquivo(
        int $idProcesso,
        int $idLiquidacao,
        bool $isEdicao = false,
        string $nomeArquivoAntigo = '',
        string $observacaoArquivo = ''
    ): string {
        if ($isEdicao) {
            (new Sinistro2_Model_ProcessosObservacoes())->insert([
                'ds_observacao' => $observacaoArquivo,
                'id_processo' => $idProcesso,
                'ds_nome_arquivo' => $nomeArquivoAntigo
            ]);

            if (empty($_FILES)) {
                return '';
            }

            (new Sinistro2_Model_ProcessosArquivos)->deletar($idProcesso, $nomeArquivoAntigo, 'DIFERENCA_INDENIZACAO');
            unlink(APPLICATION_PATH. "upload_files/sinistro_processo/{$nomeArquivoAntigo}");
        }

        $nomeArquivo = (new Sinistro2_Service_SalvarArquivoProcesso())->executar(
            $idProcesso,
            (new Sistema_Model_TipoArquivoProcesso)->getIdArquivo('DIFERENCA_INDENIZACAO')
        );

        if (!$isEdicao) {
            (new Sinistro2_Model_ProcessosObservacoes())->insert([
                'ds_observacao' => $observacaoArquivo,
                'id_processo' => $idProcesso,
                'ds_nome_arquivo' => $nomeArquivo
            ]);
        }

        (new Sinistro2_Model_LiquidacaoPagamentoAdicional())->update(
            ['ds_nome_arquivo' => $nomeArquivo],
            "id_liquidacao = {$idLiquidacao} AND fl_ativo IS TRUE"
        );

        return $nomeArquivo;
    }

    private function enviarEmailAguardandoRevisao(int $idProcesso): void
    {
        $processo = (new Sinistro2_Model_Processos())->getRow($idProcesso);
		$proposta = (new Seguro_Model_Propostas())->getRow($processo->id_proposta);

        $content = "Existe um pagamento adicional acima de R$ 20.000,00 que precisa ser revisado para a proposta {$proposta->id_proposta_mae}";
        try {
            $mail = new Agro_Mail();
            $mail->clearFrom();
            $mail->setFrom('ti@agrobrasilseguros.com.br', 'AgroBrasil - Agronet 2.0');
            $mail->addTo('marcia.correa@agrobrasilseguros.com.br');
            $mail->addTo('tiago.zschornack@agrobrasilseguros.com.br');
            $mail->addTo('tatiana.tondim@agrobrasilseguros.com.br');
            $mail->setBody($content);
            $mail->setSubject('Diferença de Indenização');
            $mail->send();
        } catch (Exception $e) {
            throw new Exception('Erro ao enviar e-mail.');
        }
    }
}
