<?php declare(strict_types=1);

class Seguro_Service_EnviarFormularioEcmPlugEssor
{
    const PDF_COTACAO = 1;
    const PDF_PROPOSTA = 2;
    const PDF_APOLICE = 3;
    
    const DESCRICAO_TIPOS_PDF = [
        self::PDF_COTACAO => 'COTACAO',
        self::PDF_PROPOSTA => 'PROPOSTA',
        self::PDF_APOLICE => 'APOLICE'
    ];

    private Seguro_Service_SalvarArquivoFormularioEcmPlugEssor $serviceSalvarArquivoFormularioEcm;
    private Log_Model_EnvioFormularioEcmPlugEssor $log;
    private Seguro_Service_NotificarErroEcmPlugEssor $serviceNotificarErro;

    public function __construct()
    {
        $this->serviceSalvarArquivoFormularioEcm = new Seguro_Service_SalvarArquivoFormularioEcmPlugEssor();
        $this->log = new Log_Model_EnvioFormularioEcmPlugEssor();
        $this->serviceNotificarErro = new Seguro_Service_NotificarErroEcmPlugEssor();
    }

    public function executar(
        Seguro_Model_Row_Proposta $proposta,
        int $tipoEnvio,
        string $pdfBase64,
        int $idEndossoErp
    ): void
    {
        try {
            $modelProposta = new Seguro_Model_Propostas();

            $nomeArquivo = $modelProposta->getNomeArquivoEnvioEcm($proposta, $tipoEnvio);
            $dto = $this->getDto($nomeArquivo, (int) $idEndossoErp, $tipoEnvio, $pdfBase64);

            $this->enviarParaEcm($dto, $proposta->id, $nomeArquivo, $idEndossoErp, $tipoEnvio, $pdfBase64);
            
        } catch (Throwable $e) {
            $erro = [
				'origem_erro' => 'AGRONET',
				'tipo_erro' => get_class($e),
				'mensagem' => $e->getMessage(),
				'arquivo' => $e->getFile(),
            	'linha' => $e->getLine(),
            	'trace' => $e->getTraceAsString()
			];
            
            $nomeArquivo = (new Seguro_Model_Propostas())->getNomeArquivoEnvioEcm($proposta, $tipoEnvio);
            $caminhoArquivo = (new Seguro_Service_SalvarArquivoFormularioEcmPlugEssor())
                ->executar($nomeArquivo, $tipoEnvio, $pdfBase64);
            
            $this->salvarLogErro($proposta->id, $tipoEnvio, $erro, $caminhoArquivo, $idEndossoErp);
            $this->serviceNotificarErro->executar($proposta->id, $tipoEnvio, $caminhoArquivo, $erro);
        }
    }

    private function enviarParaEcm(
        Agro_Essor_Plug_Dto_FormulariosResquest $dto,
        int $idProposta,
        string $nomeArquivo,
        int $idEndossoErp,
        int $tipoEnvio,
        string $pdfBase64
    ) {
        $formularios = new Agro_Essor_Plug_Formularios();
        
        try {
            list($response, $httpCode) = $formularios->execute($dto);
        } catch (\Throwable $e) {
            $response = [
                'origem_erro' => 'PLUG',
                'tipo_erro' => get_class($e),
                'mensagem' => $e->getMessage(),
                'arquivo' => $e->getFile(),
            	'linha' => $e->getLine(),
            	'trace' => $e->getTraceAsString()
            ];

            $httpCode = 500;
        }

        if (empty($response['idEndosso']) || $httpCode != 200) {
            // Em caso de erro salva arquivo no Agronet
            $caminhoArquivo = $this->serviceSalvarArquivoFormularioEcm->executar($nomeArquivo, $tipoEnvio, $pdfBase64);
            $response['origem_erro'] = 'PLUG';

            $this->salvarLogErro($idProposta, $tipoEnvio, $response, $caminhoArquivo, $idEndossoErp);
            
            if ($this->log->getNumeroTentativasComErro($idProposta, $tipoEnvio) < 5) {
                (new Seguro_Service_EnviarFormularioFilaEcmPlugEssor())->executar([
                    new Seguro_Dto_FormularioFilaEcmPlugEssor(
                        $idProposta,
                        $tipoEnvio,
                        $pdfBase64
                    )
                ]);
            } else {
                $this->serviceNotificarErro->executar($idProposta, $tipoEnvio, $caminhoArquivo, $response);
            }

        } else {
            $this->salvarLogSucesso($idProposta, $tipoEnvio, $response['idEndosso'], $response['idDocumento'], $nomeArquivo);

            // Deleta arquivo armazenado no agronet quando envio para ECM for bem sucedido
            $caminhoArquivo = Seguro_Service_SalvarArquivoFormularioEcmPlugEssor::getCaminhoArquivoPorTipoEnvio($tipoEnvio)
                . "/{$nomeArquivo}";
            
            if (file_exists($caminhoArquivo)) {
                unlink($caminhoArquivo);
            }
        }
    }


    private function getDto(
        string $nomeArquivo,
        int $idEndossoErp,
        int $tipoEnvio,
        string $pdfBase64
    ): Agro_Essor_Plug_Dto_FormulariosResquest
    {
        $codigoObservacao = '';

        if ($tipoEnvio == self::PDF_COTACAO) {
            $codigoObservacao = Agro_Essor_Plug_Enum_CodigoObservacao::COTACAO;
        } elseif ($tipoEnvio == self::PDF_PROPOSTA) {
            $codigoObservacao = Agro_Essor_Plug_Enum_CodigoObservacao::PROPOSTA;
        } elseif($tipoEnvio == self::PDF_APOLICE) {
            $codigoObservacao = Agro_Essor_Plug_Enum_CodigoObservacao::APOLICE;
        }

        return new Agro_Essor_Plug_Dto_FormulariosResquest(
            Agro_Essor_Plug_Enum_CodigoTipoDocumento::ENDOSSO,
            Agro_Essor_Plug_Enum_CodigoDominio::ENDOSSO,
            Agro_Essor_Plug_Enum_CodigoTratamentoDocumento::NORMAL,
            $idEndossoErp,
            $nomeArquivo,
            $codigoObservacao,
            pathinfo($nomeArquivo, PATHINFO_FILENAME),
            $pdfBase64
        );
    }

    private function salvarLog(
        int $idProposta,
        int $tipoEnvio,
        bool $sucesso,
        array $dados = []
    ): void {
        $payload = [
            'id_proposta' => $idProposta,
            'fl_sucesso_envio' => $sucesso,
            'ds_chave_tipo_envio' => self::DESCRICAO_TIPOS_PDF[$tipoEnvio] ?? '',
        ];

        $this->log->save(array_merge($payload, $dados));
    }

    private function salvarLogSucesso(
        int $idProposta,
        int $tipoEnvio,
        int $idEndosso,
        int $idDocumento,
        string $nomeArquivo
    ): void
    {
        $this->salvarLog($idProposta, $tipoEnvio, true, [
            'id_endosso_erp' => $idEndosso,
            'id_documento_erp' => $idDocumento,
            'ds_nome_arquivo_erp' => $nomeArquivo
        ]);
    }

    private function salvarLogErro(
        int $idProposta,
        int $tipoEnvio,
        array $erro,
        ?string $caminhoArquivo = null,
        ?int $idEndossoErp = null
    ): void
    {
        $this->salvarLog($idProposta, $tipoEnvio, false, [
            'id_endosso_erp' => $idEndossoErp,
            'fl_sucesso_envio' => false,
            'ds_caminho_arquivo_agronet' => $caminhoArquivo,
            'json_erro' => json_encode($erro),
        ]);
    }
}
