<?php

use Mpdf\HTMLParserMode;
use Mpdf\Mpdf;
use Mpdf\Config\ConfigVariables;
use Mpdf\Config\FontVariables;
use Mpdf\MpdfException;
use Mpdf\Output\Destination;

class Seguro_Service_GeracaoApolice
{
    private const PREMIO_ZERADO = 'R$ 0,00';

    private ?array $beneficiarios;
    private array $coberturaPrincipal;
    private array $coberturasAdicionais;
    private array $cobranca;
    private array $condicoesEspeciaisCoberturaPrincipal;
    private array $condicoesEspeciaisCoberturasAdicionais;
    private array $corretor;
    private Zend_Db_Table_Row_Abstract $corretorEndereco;
    private array $dadosEndosso;
    private bool $isEndosso;
    private array $itensSegurados;
    private Mpdf $mpdf;
    private bool $producaoGarantida;
    private array $produto;
    private array $proponente;
    private array $propriedade;
    private Zend_Db_Table_Row_Abstract $proposta;
    private Seguro_Service_Apolice $serviceApolice;
    private Log_Service_XmlTransmissaoProposta $serviceXmlTransmissaoProposta;
    private string $valorLmga;
    private int $numeroEndosso;
    private Agro_TemplateRenderer $templateRenderer;
    private string $dataEmissao;
    private string $dataEmissaoApoliceOriginal;

    /**
     * @param Seguro_Service_Apolice $serviceApolice
     * @throws MpdfException
     * @throws Zend_Db_Table_Exception
     * @throws Zend_Exception
     */
    public function __construct(Seguro_Service_Apolice $serviceApolice)
    {
        $defaultConfig = (new ConfigVariables())->getDefaults();
        $fontDirs = $defaultConfig['fontDir'];

        $defaultFontConfig = (new FontVariables())->getDefaults();
        $fontData = $defaultFontConfig['fontdata'];

        $fontsPath = APPLICATION_PATH . '/../library/fonts';

        $this->mpdf = new Mpdf([
            'margin_top' => 5,
            'margin_left' => 5,
            'margin_right' => 5,
            'margin_bottom' => 10,
            'fontDir' => array_merge($fontDirs, [$fontsPath]),
            'fontdata' => $fontData + [
                    'ptmono' => [
                        'R' => 'PTMono-Regular.ttf',
                    ],
                ],
            'default_font' => 'ptmono',
            'format' => 'A4',
            'default_font_size' => 12,
            'tempDir' => APPLICATION_PATH . '/upload_files/temp',
        ]);
        $this->condicoesEspeciaisCoberturasAdicionais = [];
        $this->templateRenderer = new Agro_TemplateRenderer();
        $this->proposta = $serviceApolice->getProposta();
        $this->beneficiarios = $this->proposta->beneficiarios();
        $this->coberturaPrincipal = $this->proposta->coberturas_contratadas('principal');
        $this->coberturasAdicionais = $this->proposta->coberturas_contratadas('adicional');
        $this->cobranca = $this->proposta->cobranca();
        $this->corretor = $this->proposta->corretor();
        
        $enderecoCorretor = (new Sistema_Model_CorretoresEnderecos())->getEnderecosFromCorretor(
            $this->corretor['id']
        );

        if ($enderecoCorretor->count() === 0) {
            $mensagem = "Não foi possível realizar o download da Apólice. Pedimos que entre em contato com o";
            $mensagem .= " Atendimento para regularização de seu cadastro.";
            throw new Zend_Exception($mensagem, 1);
        }

        $this->corretorEndereco = $enderecoCorretor->current();
        $this->itensSegurados = $this->proposta->itens_segurados();
        $this->producaoGarantida = $this->proposta->atributos('PROPRIEDADE', 'PROD_PRODUCAO_GARANTIDA');
        $this->produto = $this->proposta->produto();
        $this->proponente = $this->proposta->proponente();
        $this->propriedade = $this->proposta->propriedade();
        $this->serviceApolice = $serviceApolice;
        $this->numeroEndosso = (int)$this->proposta->versao_endosso(false);
        $this->isEndosso = $this->numeroEndosso > 0;
        $this->serviceXmlTransmissaoProposta = new Log_Service_XmlTransmissaoProposta(
            (int)$this->proposta['id'],
            $this->isEndosso
        );
        $this->valorLmga = Agro_Util::formatDbCurrency($this->proposta->lmga());
        $this->dataEmissao = $this->serviceApolice->retornarDataEmissao(Agro_Utils_Date::FORMAT_PT_BR);
        $this->dataEmissaoApoliceOriginal = $this->serviceApolice->retornarDataEmissaoApoliceOriginal(Agro_Utils_Date::FORMAT_PT_BR);

        $this->buscarCondicoesEspeciais();
        $this->dadosEndosso();
    }

    /**
     * @throws MpdfException
     */
    private function ajustesCSS(): void
    {
        $sanitizedPath = realpath($_SERVER['DOCUMENT_ROOT'] . "/resources/css/seguro/apolice/geracaopdf.css");
        $css = file_get_contents($sanitizedPath);

        $this->mpdf->WriteHTML($css, HTMLParserMode::HEADER_CSS);
    }

    /**
     * @throws MpdfException
     */
    private function assinatura(): void
    {
        $data = str_pad(date('d'), 2, '0', STR_PAD_LEFT) . " de " . strtolower(Agro_Util::MAP_DESCRICAO_MES[date('m')]);
        $data .= " de " . date('Y');
        $this->mpdf->WriteHTML(
            $this->templateRenderer->renderizar(
                'seguro/apolice/assinatura.html.tpl',
                ['data' => $data]
            ),
            HTMLParserMode::HTML_BODY
        );
    }

    /**
     * @throws MpdfException
     */
    private function blocoDadosBeneficiario(): void
    {
        foreach ($this->beneficiarios as $beneficiario) {
            $entityBeneficiario = Seguro_Factory_Beneficiario::createFromDto(
                Seguro_Dto_PropostaBeneficiario::fromArray($beneficiario)
            );
            $enderecoBeneficiario = $entityBeneficiario->getEnderecoBeneficiario();
            $percentualParticipacao = $this->serviceXmlTransmissaoProposta->getPercentualParticipacaoBeneficiario(
                $beneficiario['nr_cpf_cnpj']
            );

            $this->mpdf->WriteHTML(
                $this->templateRenderer->renderizar(
                    'seguro/apolice/dados_beneficiario.html.tpl',
                    [
                        'nome_razao_social' => $entityBeneficiario->getNomeBeneficiarioImpressao(),
                        'nome_social' => $entityBeneficiario->getBeneficiario()->getNomeSocial(),
                        'cpf_cnpj' => $entityBeneficiario->getBeneficiario()->getCpfCnpj(),
                        'endereco' => $enderecoBeneficiario->getEnderecoComNumeroComplemento(),
                        'bairro' => $enderecoBeneficiario->getBairro(),
                        'cep' => $enderecoBeneficiario->getCep(),
                        'cidade_uf' => $enderecoBeneficiario->getMunicipioUf(),
                        'percentual_participacao' => "{$percentualParticipacao}%",
                    ]
                ),
                HTMLParserMode::HTML_BODY
            );
        }

        if (count($this->beneficiarios) > 0) {
            $this->mpdf->WriteHTML('<hr class="hr_bold">', HTMLParserMode::HTML_BODY);
        }
    }

    /**
     * @throws MpdfException
     */
    private function blocoDadosCorretoras(): void
    {
        $endereco = "{$this->corretorEndereco['ds_endereco_rua']}, {$this->corretorEndereco['ds_endereco_nro']}";
        if (!empty($this->corretorEndereco['ds_endereco_complemento'])) {
            $endereco .= ", {$this->corretorEndereco['ds_endereco_complemento']}";
        }

        $this->mpdf->WriteHTML(
            $this->templateRenderer->renderizar(
                'seguro/apolice/dados_corretora.html.tpl',
                [
                    'razao_social' => $this->corretor['ds_nome_corretor'],
                    'cnpj' => $this->corretor['cpf_cnpj'],
                    'susep' => $this->corretor['nr_susep'],
                    'endereco' => $endereco,
                    'bairro' => $this->corretorEndereco['ds_endereco_bairro'],
                    'cep' => $this->corretorEndereco['ds_endereco_cep'],
                    'cidade_uf' => "{$this->corretorEndereco['ds_nome_municipio']}/{$this->corretorEndereco['ds_sigla']}",
                    'telefone' => $this->corretor['ds_telefone_contato_seguro_agricola'],
                ]
            )
        );
    }

    /**
     * @throws MpdfException
     */
    private function blocoDadosPropriedade(): void
    {
        $endereco = "{$this->propriedade['ds_endereco']}, {$this->propriedade['ds_endereco_nro']}";
        if (!empty($this->propriedade['ds_endereco_complemento'])) {
            $endereco .= ", {$this->propriedade['ds_endereco_complemento']}";
        }

        $coordenadas = explode(',', $this->propriedade['ds_coordenadas']);

        $this->mpdf->WriteHTML(
            $this->templateRenderer->renderizar(
                'seguro/apolice/dados_propriedade.html.tpl',
                [
                    'endereco' => $endereco,
                    'bairro' => $this->propriedade['ds_endereco_bairro'],
                    'cep' => $this->propriedade['ds_endereco_cep'],
                    'cidade_uf' => "{$this->propriedade['ds_nome_municipio']}/{$this->propriedade['ds_sigla']}",
                    'codigo_bacen' => $this->propriedade['cd_bacen'],
                    'nome_propriedade' => $this->propriedade['ds_nome_propriedade'],
                    'coordenadas' => implode(
                        ', ',
                        Agro_Util::convertDecimalToDMSString(
                            Agro_Util::calcula_coordenadas(trim($coordenadas[0])),
                            Agro_Util::calcula_coordenadas(trim($coordenadas[1]))
                        )
                    ),
                ]
            ),
            HTMLParserMode::HTML_BODY
        );
    }

    /**
     * @throws MpdfException
     */
    private function blocoDadosSegurado(): void
    {
        if ($this->proponente['tp_pessoa'] === 'F') {
            $this->blocoDadosSeguradoFisico();
        } else {
            $this->blocoDadosSeguradoJuridico();
        }
    }

    /**
     * @throws MpdfException
     */
    private function blocoDadosSeguradoFisico(): void
    {
        $dadosSegurado = [
            'nome_social' => $this->proponente['ds_nome_social'],
            'orgao_expedicao' => $this->proponente['ds_nome_orgao'],
            'data_nascimento' => Agro_Util::formatDate(
                $this->proponente['dt_nascimento'],
                Agro_Utils_Date::FORMAT_PT_BR
            ),
            'documento' => $this->proponente['ds_documento_numero'],
            'data_expedicao' => Agro_Util::formatDate(
                $this->proponente['dt_documento_exp'],
                Agro_Utils_Date::FORMAT_PT_BR
            ),
        ];

        $dadosSegurado = array_merge($dadosSegurado, $this->camposPadraoSegurado());

        $this->mpdf->WriteHTML(
            $this->templateRenderer->renderizar(
                'seguro/apolice/dados_segurado_fisico.html.tpl',
                $dadosSegurado
            ),
            HTMLParserMode::HTML_BODY
        );
    }

    /**
     * @throws MpdfException
     */
    private function blocoDadosSeguradoJuridico(): void
    {
        $this->mpdf->WriteHTML(
            $this->templateRenderer->renderizar(
                'seguro/apolice/dados_segurado_juridico.html.tpl',
                $this->camposPadraoSegurado()
            ),
            HTMLParserMode::HTML_BODY
        );
    }

    /**
     * @throws MpdfException
     */
    private function blocoDadosSeguro(): void
    {
        $this->mpdf->WriteHTML(
            $this->templateRenderer->renderizar(
                'seguro/apolice/dados_seguro.html.tpl',
                [
                    'cultura' => $this->produto['ds_nome_cultura'],
                    'area_total_cultura' => $this->proposta->area(),
                    'lmga' => "R$ {$this->valorLmga}",
                    'codigo_bacen_cultura' => $this->produto['codigo_bacen_cultura'],
                    'total_itens_segurados' => $this->proposta->count_itens_segurados(),
                    'premio_total' => $this->tratarTextosPremio(
                        $this->cobranca['premio_liquido'] + $this->proposta['vl_custo_apolice']
                    ),
                ]
            ),
            HTMLParserMode::HTML_BODY
        );
    }

    /**
     * @throws MpdfException
     */
    private function blocoDemonstrativoCoberturasContratadas(): void
    {
        $descricao = !empty($this->condicoesEspeciaisCoberturaPrincipal)
            ? trim($this->condicoesEspeciaisCoberturaPrincipal['ds_titulo'])
            : $this->coberturaPrincipal['ds_nome_cobertura'];

        $coberturas = [];
        $coberturas[] = [
            'descricao' => $descricao,
            'tipo' => 'Principal',
            'franquia_nc' => str_replace('.', ',', $this->coberturaPrincipal['vl_franquia']) . "%",
            'lmi' => "R$ {$this->valorLmga}",
            'premio' => $this->tratarTextosPremio($this->coberturaPrincipal['vl_premio']),
        ];

        foreach ($this->coberturasAdicionais as $coberturasAdicional) {
            $condicoesEspeciais = $this->retornarCondicaoEspecialCoberturaAdicional((int)$coberturasAdicional['id']);
            $descricao = !empty($condicoesEspeciais)
                ? trim($condicoesEspeciais['ds_titulo'])
                : $coberturasAdicional['ds_nome_cobertura'];

            $franquiaNc = $coberturasAdicional['fl_exibir_franquia']
                ? str_replace('.', ',', $coberturasAdicional['vl_franquia']) . "%"
                : '-';

            if ($coberturasAdicional['ds_chave_cobertura'] === 'COB_PROTECAO_FITO') {
                $valorLmi = $this->proposta->area_liquida() * 100;
            } else {
                $valorLmi = ($coberturasAdicional['vl_lmi'] * $this->proposta->lmga()) / 100;
            }

            $valorPremio = $coberturasAdicional['vl_premio']
                ? $this->tratarTextosPremio($coberturasAdicional['vl_premio'])
                : '-';

            $coberturas[] = [
                'descricao' => $descricao,
                'tipo' => 'Adicional',
                'franquia_nc' => $franquiaNc,
                'lmi' => "R$ " . Agro_Util::formatDbCurrency($valorLmi),
                'premio' => $valorPremio,
            ];
        }

        $this->mpdf->WriteHTML(
            $this->templateRenderer->renderizar(
                'seguro/apolice/demonstrativo_coberturas_contratadas.html.tpl',
                [
                    'cabecalho_franquia_nc' => $this->producaoGarantida ? 'NC' : 'Franquia',
                    'colunas_coberturas_width' => 'class="colunas_coberturas_width"',
                    'table_margin_top' => 'class="margin_top"',
                    'coberturas' => $coberturas,
                ]

            ),
            HTMLParserMode::HTML_BODY
        );
    }

    /**
     * @throws MpdfException
     */
    private function blocoInformacoes(): void
    {
        $dateTimeEmissao =  DateTime::createFromFormat('d/m/Y', $this->dataEmissaoApoliceOriginal);

        $produtoConfig = (new Produto_Model_ProdutoConfig())->getConfiguracaoByData(
            $this->proposta['id_produto'],
            $dateTimeEmissao
        );

        $descricao = nl2br(preg_replace("/\r\n?/", "\n", $produtoConfig['ds_frase_risco']), false);

        $this->mpdf->WriteHTML(
            "<span><b> INFORMAÇÕES IMPORTANTES PARA O SEGURADO</b></span>
             <div style='padding-top: 5px; text-align: justify;'>{$descricao}</div>",
            HTMLParserMode::HTML_BODY
        );
    }

    /**
     * @throws MpdfException
     */
    private function blocoMotivosObservacoesEndosso(): void
    {
        if (!$this->isEndosso) {
            return;
        }

        $this->mpdf->WriteHTML(
            "<span><b> MOTIVO DO ENDOSSO E OUTRAS OBSERVAÇÕES DO SEGURO</b></span>
             <div style='padding-top: 5px; text-align: justify;'>{$this->dadosEndosso['observacoes']}</div>
             <hr class='hr_bold'>",
            HTMLParserMode::HTML_BODY
        );
    }

    /**
     * @throws MpdfException
     */
    private function blocoPremio(): void
    {
        $iof = $this->cobranca['iof'] === 'isento' ? "0.00" : $this->cobranca['iof'];
        $premioPagar = $this->dadosEndosso['restituicao']
            ? 0
            : $this->cobranca['premio_liquido'] + $this->proposta['vl_custo_apolice'];
        $parcelas = [];
        $subvencaoEstadual = $subvencaoFederal = 0;
        $totalParcelas = count($this->cobranca['parcelamento']);

        foreach ($this->cobranca['parcelamento'] as $parcela) {
            $subvencaoEstadual += $parcela['vl_subvencao_estadual'];
            $subvencaoFederal += $parcela['vl_subvencao_federal'];
            
            if ($parcela['vl_segurado'] < 0) {
                $parcela['vl_segurado'] *= -1;
            }

            if ($this->dadosEndosso['restituicao']) {
                $premioPagar += $parcela['vl_segurado'];
            }

            $parcelas[] = [
                'numero_parcela' => $parcela['nr_parcela'],
                'vencimento' => !$this->dadosEndosso['semMovimento']
                    ? Agro_Util::formatDate($parcela['dt_vencimento'], Zend_Date::DATES)
                    : '-',
                'premio_total_parcela' => $this->tratarTextosPremio($parcela['vl_segurado']),
                'numero_documento' => !$this->dadosEndosso['semMovimento'] ? $parcela['ds_identificador'] : '-',
                'pagador' => 'Segurado',
            ];
        }

        if ($subvencaoEstadual > 0 || ($subvencaoEstadual != 0 && $this->dadosEndosso['restituicao'])) {
            if ($subvencaoEstadual < 0) {
                $subvencaoEstadual *= -1;
            }

            if ($this->dadosEndosso['restituicao']) {
                $premioPagar += $subvencaoEstadual;
            }

            $totalParcelas++;
            $parcelas[] = [
                'numero_parcela' => $totalParcelas,
                'vencimento' => '-',
                'premio_total_parcela' => $this->tratarTextosPremio($subvencaoEstadual),
                'numero_documento' => '-',
                'pagador' => 'Subvenção Estadual',
            ];
        }

        if ($subvencaoFederal > 0 || ($subvencaoFederal != 0 && $this->dadosEndosso['restituicao'])) {
            if ($subvencaoFederal < 0) {
                $subvencaoFederal *= -1;
            }

             if ($this->dadosEndosso['restituicao']) {
                $premioPagar += $subvencaoFederal;
            }

            $totalParcelas++;
            $parcelas[] = [
                'numero_parcela' => $totalParcelas,
                'vencimento' => '-',
                'premio_total_parcela' => $this->tratarTextosPremio($subvencaoFederal),
                'numero_documento' => '-',
                'pagador' => 'Subvenção Federal',
            ];
        }

        $this->mpdf->WriteHTML(
            $this->templateRenderer->renderizar(
                'seguro/apolice/premio.html.tpl',
                [
                    'premio_liquido' => $this->tratarTextosPremio($this->cobranca['premio_liquido']),
                    'custo_apolice' => $this->tratarTextosPremio($this->proposta['vl_custo_apolice']),
                    'iof' => $this->tratarTextosPremio($iof),
                    'premio_pagar' => $this->tratarTextosPremio($premioPagar),
                    'label1' => !$this->dadosEndosso['restituicao'] ? 'Prêmio a Pagar' : 'Prêmio a Restituir',
                    'label2' => !$this->dadosEndosso['restituicao'] ? 'Pagador' : 'Restituído',
                    'parcelas' => $parcelas
                ]
            ),
            HTMLParserMode::HTML_BODY
        );
    }

    /**
     * @throws MpdfException
     */
    private function blocoRiscosCoberturasContratadas(): void
    {
        $idCoberturaPrincipal = (int)$this->coberturaPrincipal['id'];
        $idProposta = (int)$this->proposta['id'];
        $itens = [];
        $centroides = (new Seguro_Service_PropostaCroquiTalhao())->getCentroidesTalhoes($idProposta);
        $multirrisco = in_array(
            $idCoberturaPrincipal,
            [Produto_Model_Coberturas::COB_MULTIRISCO, Produto_Model_Coberturas::COB_MULTIRISCO_II]
        );

        foreach ($this->itensSegurados as $itemSegurado) {
            $centroide = isset($centroides[$itemSegurado['is_item']])
                ? $centroides[$itemSegurado['is_item']]['ds_coordenadas_centroide']
                : $itemSegurado['is_coordenadas_geograficas'];

            $coordenadas = explode(',', $centroide);
            $mostrarLmg = in_array(
                $idCoberturaPrincipal,
                [Produto_Model_Coberturas::COB_GRANIZO, Produto_Model_Coberturas::COB_MULTIRISCO]
            );

            $itensCobertura = [];
            $itensCobertura[] = $this->montarValoresItensCoberturas(
                $idProposta,
                (int)$itemSegurado['is_item'],
                true,
                $idCoberturaPrincipal,
                $multirrisco
            );

            foreach ($this->coberturasAdicionais as $coberturasAdicional) {
                $itensCobertura[] = $this->montarValoresItensCoberturas(
                    $idProposta,
                    (int)$itemSegurado['is_item'],
                    false,
                    (int)$coberturasAdicional['id'],
                    $multirrisco
                );
            }

            $itens[] = [
                'numero_item' => $itemSegurado['is_item'],
                'nome_item' => $itemSegurado['is_descricao_item'],
                'area' => str_replace('.', ',', $itemSegurado['is_area']),
                'valor_tonelada' => Agro_Util::formatDbCurrency($itemSegurado['is_valor_tonelada']),
                'variedade' => $itemSegurado['is_nome_variedades'],
                'produtividade' => str_replace('.', ',', $itemSegurado['is_produtividade']),
                'lmg' => "R$ " . Agro_Util::formatDbCurrency($itemSegurado['is_lmga_parcial']),
                'class_lmg' => $mostrarLmg ? "" : "td_hide",
                'coordenadas' => implode(
                    ', ',
                    Agro_Util::convertDecimalToDMSString(
                        Agro_Util::calcula_coordenadas(trim($coordenadas[0])),
                        Agro_Util::calcula_coordenadas(trim($coordenadas[1]))
                    )
                ),
                'item_coberturas' => $itensCobertura,
                'label_coluna_pg_franquia' => $multirrisco ? "PG (ton/ha)" : "Franquia (R$)",
                'colunas_coberturas_width' => 'class="colunas_coberturas_width"',
            ];
        }

        $this->mpdf->WriteHTML(
            $this->templateRenderer->renderizar(
                'seguro/apolice/riscos_coberturas_contratadas.html.tpl',
                [
                    'riscos_coberturas_contratadas' => $itens,
                ]

            ),
            HTMLParserMode::HTML_BODY
        );
    }

    /**
     * @throws MpdfException
     */
    private function blocoTextosRiscosCoberturasConfiguracao(): void
    {
        $expressaoSubstituir = "/\r\n?/";
        $modelProdutoCoberturaConfig = new Produto_Model_ProdutoCoberturaConfig();

        $dateTimeEmissao =  DateTime::createFromFormat('d/m/Y', $this->dataEmissaoApoliceOriginal);

        $produtoCoberturaConfig = $modelProdutoCoberturaConfig->getConfiguracaoByData(
            $this->produto['id'],
            $this->coberturaPrincipal['id'],
            $dateTimeEmissao
        );
    
        $descricao = nl2br(
            preg_replace($expressaoSubstituir, "\n", $produtoCoberturaConfig['ds_frase_condicoes_particulares']),
            false
        );

        if (!empty($descricao)) {
            $this->mpdf->WriteHTML(
                "<div style='padding-bottom: 5px text-align: justify;'>{$descricao}</div>",
                HTMLParserMode::HTML_BODY
            );
        }

        foreach ($this->coberturasAdicionais as $coberturaAdicional) {
            $produtoCoberturaConfig = $modelProdutoCoberturaConfig->getConfiguracaoByData(
                $this->produto['id'],
                $coberturaAdicional['id'],
                $dateTimeEmissao
            );

            if (empty($produtoCoberturaConfig)) {
                continue;
            }

            $descricao = nl2br(
                preg_replace($expressaoSubstituir, "\n", $produtoCoberturaConfig['ds_frase_condicoes_particulares']),
                false
            );

            if (!empty($descricao)) {
                $this->mpdf->WriteHTML(
                    "<div style='padding-bottom: 5px'>{$descricao}</div>",
                    HTMLParserMode::HTML_BODY
                );
            }
        }
    }

    /**
     * @throws MpdfException
     */
    private function blocoVigenciaSeguro(): void
    {
        $dataInicioVigencia = Agro_Util::formatDate($this->proposta['dt_vigencia_inicio'], Agro_Utils_Date::FORMAT_PT_BR);
        $dataFimVigencia = Agro_Util::formatDate($this->proposta['dt_vigencia_fim'], Agro_Utils_Date::FORMAT_PT_BR);
        $texto = "<b>VIGÊNCIA DO SEGURO:</b> das 24h do dia $dataInicioVigencia às 24h do dia $dataFimVigencia";
        $texto .= '<hr class="hr_bold">';

        $this->mpdf->WriteHTML($texto, HTMLParserMode::HTML_BODY);
    }

    private function buscarCondicoesEspeciais(): void
    {
        $dateTimeEmissao =  DateTime::createFromFormat('d/m/Y', $this->dataEmissaoApoliceOriginal);

        $modelCondicoesEspeciais = new Produto_Model_CondicoesEspeciais();
        $this->condicoesEspeciaisCoberturaPrincipal = $modelCondicoesEspeciais->getByProdutoCobertura(
            $this->produto['id'],
            $this->coberturaPrincipal['id'],
            $dateTimeEmissao
        )->toArray();

        foreach ($this->coberturasAdicionais as $coberturasAdicional) {
            $rs = $modelCondicoesEspeciais->getByProdutoCobertura(
                $this->produto['id'],
                $coberturasAdicional['id'],
                $dateTimeEmissao
            );

            if (!empty($rs)) {
                 $this->condicoesEspeciaisCoberturasAdicionais[] = $rs->toArray();
            }
        }
    }

    /**
     * @throws Zend_Db_Table_Exception
     */
    private function dadosEndosso(): void
    {
        $this->dadosEndosso = ['semMovimento' => false, 'restituicao' => false];

        if ($this->isEndosso) {
            $tipoEndosso = (int)(new Endosso_Model_Propostas())
                ->find($this->proposta['id'])
                ->current()
                ->tipo_endosso_proposta();
        
            $this->dadosEndosso['tituloDireita'] = Seguro_Enum_TipoEndosso::getDescricaoApoliceEndosso($tipoEndosso);
            $this->dadosEndosso['semMovimento'] = Seguro_Enum_TipoEndosso::isSemMovimento($tipoEndosso);
            $this->dadosEndosso['restituicao'] = Seguro_Enum_TipoEndosso::isRestituicao($tipoEndosso);
            $this->dadosEndosso['observacoes'] = '';

            $observacoes = $this->proposta->observacoes();

            if (!empty($observacoes)) {
                $this->dadosEndosso['observacoes'] = $observacoes[0]['ds_observacao'];
            }
        }
    }

    /**
     * @throws Zend_Exception
     * @throws MpdfException
     */
    private function cabecalhoRodapePaginas(): void
    {
        $this->mpdf->SetHTMLHeader(
            $this->templateRenderer->renderizar(
                'seguro/apolice/header.html.tpl',
                [
                    'cnpj_essor' => '14.525.684/0001-50',
                    'numero_proposta_completo' => preg_replace('/\D/', '', $this->proposta->doc()),
                    'data_emissao' => $this->dataEmissao,
                    'descricao_safra' => $this->produto['ds_nome_safra'],
                    'nome_produto' => $this->produto['ds_nome_produto'],
                    'numero_apolice' => $this->proposta['nr_apolice'],
                    'nome_cobertura_principal' => $this->coberturaPrincipal['ds_nome_cobertura'],
                    'numero_endosso' => $this->numeroEndosso,
                    'titulo_direita' => !$this->isEndosso ? 'APÓLICE' : $this->dadosEndosso['tituloDireita'],
                ]
            )
        );

        $this->mpdf->SetHTMLFooter($this->templateRenderer->renderizar('seguro/apolice/footer.html.tpl'));
    }

    private function camposPadraoSegurado(): array
    {
        $endereco = "{$this->proponente['ds_endereco_rua']}, {$this->proponente['ds_endereco_nro']}";
        if (!empty($this->proponente['ds_endereco_complem'])) {
            $endereco .= ", {$this->proponente['ds_endereco_complem']}";
        }

        $telefones = [];
        if (!empty($this->proponente['ds_tel_residencia'])) {
            $telefones[] = $this->proponente['ds_tel_residencia'];
        }

        if (!empty($this->proponente['ds_tel_propriedade'])) {
            $telefones[] = $this->proponente['ds_tel_propriedade'];
        }

        if (!empty($this->proponente['ds_tel_celular'])) {
            $telefones[] = $this->proponente['ds_tel_celular'];
        }

        return [
            'nome_razao_social' => $this->proponente['ds_nome_proponente'],
            'cpf_cnpj' => $this->proponente['cpf_cnpj'],
            'email' => $this->proponente['ds_email_proponente'],
            'endereco' => $endereco,
            'bairro' => $this->proponente['ds_endereco_bairro'],
            'cep' => $this->proponente['ds_endereco_cep'],
            'cidade_uf' => "{$this->proponente['ds_nome_municipio']}/{$this->proponente['ds_sigla']}",
            'telefones' => implode(' / ', $telefones),
        ];
    }

    /**
     * @throws MpdfException
     * @throws Zend_Exception
     */
    public function gerarPdf(): array
    {
        $this->mpdf->setAutoTopMargin = 'stretch';
        $this->mpdf->setAutoBottomMargin = 'stretch';

        $this->ajustesCSS();
        $this->cabecalhoRodapePaginas();

        $this->blocoVigenciaSeguro();
        $this->blocoDadosSegurado();
        $this->blocoDadosPropriedade();
        $this->blocoDadosBeneficiario();

        $this->mpdf->addPage();
        $this->blocoDadosCorretoras();
        $this->blocoMotivosObservacoesEndosso();
        $this->blocoDadosSeguro();
        $this->blocoDemonstrativoCoberturasContratadas();
        $this->blocoPremio();

        $this->mpdf->addPage();
        $this->blocoRiscosCoberturasContratadas();

        $this->mpdf->addPage();
        $this->blocoInformacoes();

        $this->mpdf->addPage();
        $this->blocoTextosRiscosCoberturasConfiguracao();
        $this->assinatura();

        $pdfBinary = $this->mpdf->Output('', Destination::STRING_RETURN);
        $fileName = sprintf(
            '%s_%s.pdf',
            $this->proposta['nr_apolice'],
            $this->proposta['ds_identificador_seguradora']
        );

        return [$pdfBinary, $fileName];
    }

    private function montarValoresItensCoberturas(
        int  $idProposta,
        int  $numeroItemSegurado,
        bool $coberturaPrincipal,
        int  $idCobertura,
        bool $multirrisco): array
    {
        $cobertura = $coberturaPrincipal
            ? $this->coberturaPrincipal
            : $this->coberturasAdicionais[$idCobertura];
        $condicaoEspecial = $coberturaPrincipal
            ? $this->condicoesEspeciaisCoberturaPrincipal
            : $this->retornarCondicaoEspecialCoberturaAdicional($idCobertura);

        $descricao = !empty($condicaoEspecial)
            ? trim($condicaoEspecial['ds_titulo'])
            : $cobertura['ds_nome_cobertura'];

        $codigoSeguradora = Produto_Model_ProdutosCoberturas::deParaI4Pro(
            $idProposta,
            $cobertura['codigo_cobertura_seguradora']
        );

        $importanciaSegurada = $this->serviceXmlTransmissaoProposta->getImportanciaSegurada(
            $numeroItemSegurado,
            $codigoSeguradora
        );

        $premioLiquido = $this->serviceXmlTransmissaoProposta->getValorPremioLiquido(
            $numeroItemSegurado,
            $codigoSeguradora
        );

        if ($multirrisco) {
            $franquiaPg = str_replace(
                '.',
                ',',
                $this->serviceXmlTransmissaoProposta->getProdutividadeGarantidaItem($numeroItemSegurado)
            );
        } else {
            $franquia = $this->serviceXmlTransmissaoProposta->getFranquia(
                $numeroItemSegurado,
                $codigoSeguradora
            );

            $franquiaPg = ($franquia / 100) * $importanciaSegurada;
            $franquiaPg = "R$ " . Agro_Util::formatDbCurrency($franquiaPg);
        }

        $franquiaPg = !$cobertura['fl_exibir_franquia'] && !$coberturaPrincipal ? '-' : $franquiaPg;

        return [
            'descricao' => $descricao,
            'lmi' => "R$ " . Agro_Util::formatDbCurrency($importanciaSegurada),
            'franquia_pg' => $franquiaPg,
            'premio_liquido' => $this->tratarTextosPremio($premioLiquido),
        ];
    }

    private function retornarCondicaoEspecialCoberturaAdicional(int $idCobertura): array
    {
        $condicaoEspecial = array_filter(
            $this->condicoesEspeciaisCoberturasAdicionais,
            static function ($condicaoEspecial) use ($idCobertura) {
                return (int)$condicaoEspecial['id_cobertura'] === $idCobertura;
            }
        );

        return !empty($condicaoEspecial) ? current($condicaoEspecial) : [];
    }

    private function tratarTextosPremio($valor): string
    {
        return !$this->dadosEndosso['semMovimento'] ? "R$ " . Agro_Util::formatDbCurrency($valor) : self::PREMIO_ZERADO;
    }
}