<?php
use Cake\Database\Exception\MissingExtensionException;
use Symfony\Component\Filesystem\Exception\FileNotFoundException;

require_once APPLICATION_PATH . '/modules/sistema/enums/StatusImportacaoLaudoXmlEnum.php';

class Sinistro2_RotinasController extends Agro_Controller_Action
{

    public function init()
    {
        $this->view->title = 'Sinistro » Rotinas';
        ini_set('memory_limit', '1024M');
        require_once(APPLICATION_PATH . "/../library/Agro/nusoap/nusoap.php");
    }

    public function getModel()
    {
        return new Sinistro2_Model_Rotinas();
    }

    public function getForm()
    {
        return new Sinistro2_Form_Rotinas();
    }

    public function indexobservacoesAction()
    {
        parent::indexAction();
        $this->view->title = 'Sinistro » Rotinas » Importar Observações';
    }

    public function indexindenizacoesagroAction()
    {
        parent::indexAction();

        $this->view->title = 'Sinistro » Rotinas » Importar Indenizações Agro';
        
        $this->view->paginatorPropostas = (new Sinistro2_Model_RelatorioImportacaoIndenizacao())->fetchAllPaginatorProposta(
            false, $this->getRequest()->getParam('pagePropostas'), 60, 'paginator'
        );

        $this->view->paginator = (new Sinistro2_Model_RelatorioImportacaoIndenizacao())->fetchAllPaginator(
            false, $this->getRequest()->getParam('pageHistorico'), 15, 'paginator'
        );

        $idStatus = (new Sistema_Model_Status())->getIdStatus('ENVIADA_SEGURADORA', 'LIQUIDACOES');
        $antecipacoes = (new Sinistro2_Model_AntecipacaoPagamento())->buscaAntecipacoesPorIdStatus($idStatus);
        $this->view->antecipacoes = $antecipacoes->toArray();

    }

    public function indexreservasAction()
    {
        parent::indexAction();
        $this->view->title = 'Sinistro » Rotinas » Importar Ajustes de Reservas';
    }

    public function indexcobrancavistoriasAction()
    {
        parent::indexAction();
        $this->view->title = 'Sinistro » Rotinas » Cobrança de Agendamentos e Vistorias';
    }

    public function desabilitarlaudospreliminaresAction()
    {
        parent::indexAction();
        $this->view->title = 'Sinistro » Rotinas » Desabilitar Laudos Preliminares';
    }

    public function buscarhistoricoindenizacoesagroAction()
    {
        $this->isAjax(true);
        $response['status'] = true;
        
        try {
            $this->view->paginator = (new Sinistro2_Model_RelatorioImportacaoIndenizacao())->fetchAllPaginator(
                false, $this->getRequest()->getParam('pageHistorico'), 15, 'paginator'
            );
        } catch (Exception $e) {
            $this->view->error = $e;
        }
    }

    public function importarindenizacoesagroAction()
    {
        $this->getHelper('ViewRenderer')->setNoRender();
    	$this->getHelper('layout')->disableLayout();
 
        $parametros = $this->getRequest()->getParams();
        $antecipacoes = json_decode($parametros['antecipacoes'], true);
        $transacaoAtiva = false;
        
        try {
            $idRelatorioIndenizacaoAgroAnterior = !empty($parametros['idRelatorioIndenizacaoAgro'])
                ? (int) $parametros['idRelatorioIndenizacaoAgro']
                : null;
            
            $idsLiquidacoes = $parametros['id_liquidacao_indenizacao'];
            
            if (
                !$idRelatorioIndenizacaoAgroAnterior
                && (empty($idsLiquidacoes))
            ) {
                throw new Exception('Necessário selecionar liquidações.', 1);
            }

            if ($idRelatorioIndenizacaoAgroAnterior) {
                $modelRelatorio = new Sinistro2_Model_RelatorioImportacaoIndenizacao();
                $relatorioAnterior = $modelRelatorio->find($idRelatorioIndenizacaoAgroAnterior)->current();
                
                if (empty($relatorioAnterior)) {
                    throw new Exception('Relatório não encontrado.', 1);
                }

                $idsLiquidacoes = $modelRelatorio->getIdsLiquidacoes($idRelatorioIndenizacaoAgroAnterior);
                    
                if (empty($idsLiquidacoes)) {
                    throw new Exception('Relatório não possui liquidações vinculadas.', 1);
                }
            }

            Agro_Db_Table_Abstract::getDefaultAdapter()->beginTransaction();
            $transacaoAtiva = true;

            list($csv, $fullPath) = (new Sinistro2_Service_ImportarIndenizacaoAgro())->execute(
                $idsLiquidacoes,
                $antecipacoes,
                $idRelatorioIndenizacaoAgroAnterior
            );
            
            Agro_Db_Table_Abstract::getDefaultAdapter()->commit();

            header("Content-Disposition: attachment; filename=". basename($fullPath));
            header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
            header("Cache-Control: no-store, no-cache, must-revalidate");
            header("Cache-Control: post-check=0, pre-check=0", false);
            header("Content-Length: ".strlen($csv));
            header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
            header("Content-type: text/tab-separated-values");
            header("Pragma: no-cache");

            echo $csv;
            die;
        } catch (Throwable $e) {
            if ($transacaoAtiva){
                Agro_Db_Table_Abstract::getDefaultAdapter()->rollback();
            }
            
            $mensagem = $e->getCode() == 1 ? $e->getMessage() : 'Erro ao gerar indenização de pagamento.';

            $this->getResponse()
                ->setHttpResponseCode(400) // Define o código HTTP
                ->setHeader('Content-Type', 'application/json')
                ->setBody(Zend_Json::encode(['message' => $mensagem]));
        }
    }

	public function salvarobservacoesAction()
	{
        $this->isAjax();
        $params = $this->getRequest()->getParams();
        $modelProcessosObservacoes = new Sinistro2_Model_ProcessosObservacoes();
        $modelProcessos = new Sinistro2_Model_Processos();
        $retorno = [
            "erro" => false,
            "mensagem" => "Observações salvas com sucesso.",
            "propostasErro" => [],
            "indiceLinhaSucesso" => []
        ];

        try {
            if (empty($params['cbxTipo'])) {
                throw new Exception("Nenhum tipo informado.");
            }

            $zip = new ZipArchive();
            $temArquivoLote = false;

            if (isset($_FILES['arquivoLote'])) {
                $zipFile = $zip->open($_FILES['arquivoLote']['tmp_name']);

                if ($zipFile !== true) {
                    switch ($zipFile) {
                        case ZipArchive::ER_NOZIP:
                            throw new Exception('Arquivo inválido.');

                        default:
                            throw new Exception('Erro ao abrir o arquivo compactado.');
                    }
                }

                $temArquivoLote = true;
            }
        } catch (\Throwable $th) {
            $retorno["mensagem"] = $th->getMessage();
            $retorno["erro"] = true;
            $this->getResponse()->setBody(Zend_Json::encode($retorno));
            return;
        }

        foreach ($_FILES as $indice => $file) {
            if ($indice == "arquivoLote") {
                continue;
            }

            $indiceExplode = explode('_', $indice);
            $linha = $indiceExplode[1];
            $nomeArquivo = "";
            $caminhoArquivo = "";

            try {
                Agro_Db_Table_Abstract::getDefaultAdapter()->beginTransaction();

                switch ($params['cbxTipo']) {
                    case '2':
                        $dados = [
                            trim($params["id_proposta_{$linha}"]),
                            trim($params["itens_{$linha}"]),
                            trim($params["peritos_{$linha}"]),
                            trim($params["agronomos_{$linha}"]),
                            trim($params["corretor_{$linha}"]),
                            trim($params["observacoes_{$linha}"]),
                        ];
                        $erros = $this->validarErrosNovaAvaliacao($dados);
                        $agronomos = !empty($dados[3]) ? $dados[3] : '-';
                        $observacao = "Laudo referente a nova avaliação, para o(s) item(s) {$dados[1]}, vistoria";
                        $observacao .= " realizada por {$dados[2]}, e na presença do(s) agrônomo(s) {$agronomos} e";
                        $observacao .= " corretor {$dados[4]}. Utilizar esse laudo no momento da liquidação.";
                        $observacao .= " {$dados[5]}";

                        break;

                    case '3':
                        $dados = [
                            trim($params["id_proposta_{$linha}"]),
                            trim($params["itens_{$linha}"]),
                            trim($params["percentual_dano_{$linha}"]),
                            trim($params["fito_{$linha}"]),
                            trim($params["aguardando_demais_laudos_{$linha}"]),
                            trim($params["chamado_vistoriador_{$linha}"]),
                            trim($params["chamado_corretor_{$linha}"]),
                        ];
                        $erros = $this->validarErrosRevisaoMaca($dados);
                        $observacao = "Laudos conferidos para o(s) item(s) {$dados[1]}, dano(%) {$dados[2]}, Fito";
                        $observacao .= " {$dados[3]}, aguardando demais laudos para conferir, {$dados[4]}. Chamado";
                        $observacao .= " para o vistoriador {$dados[5]}. Chamado para o corretor {$dados[6]}.";

                        break;

                    default:
                        $dados = [
                            trim($params["id_proposta_{$linha}"]),
                            trim($params["ds_observacao_{$linha}"]),
                        ];
                        $erros = $this->validarErrosObservacao($dados);
                        $observacao = $params["ds_observacao_{$linha}"];

                        break;
                }

                if (count($erros) > 0) {
                    throw new Exception(implode("<br>", $erros));
                }

                $idProcesso = $modelProcessos->getIdProcessoPropostaVigenteByProposta($dados[0]);
                $nomeArquivoEsperado = trim($params["ds_nome_arquivo_{$linha}"]);

                if ($temArquivoLote && !empty($nomeArquivoEsperado)) {
                    for ($i = 0; $i < $zip->numFiles; $i++) {
                        $arquivoAtual = $zip->getNameIndex($i);

                        if ($arquivoAtual === $nomeArquivoEsperado) {
                            $fileInfo = pathinfo($arquivoAtual);
                            $ext = Agro_Util::getExtension($fileInfo['basename']);
                            $date = date('ymdhis');
                            $nomeArquivo = "{$idProcesso}{$date}.{$ext}";
                            $caminhoArquivo = APPLICATION_PATH . '/upload_files/sinistro_processo/' . $nomeArquivo;
                            $caminhoArquivo = realpath($caminhoArquivo);

                            if (
                                $caminhoArquivo
                                && !copy("zip://{$_FILES['arquivoLote']['tmp_name']}#{$arquivoAtual}", $caminhoArquivo)
                            ) {
                                throw new Exception("Não foi possível copiar o arquivo para pasta de destino.");
                            }
                        }
                    }
                }

                if (!$temArquivoLote && !empty($file['name'])) {
                    $ext = Agro_Util::getExtension($file['name']);
                    $date = date('ymdhis');
                    $nomeArquivo = "{$idProcesso}{$date}.{$ext}";
                    $caminhoArquivo = realpath(APPLICATION_PATH . '/upload_files/sinistro_processo/' . $nomeArquivo);

                    if ($caminhoArquivo && !copy($file['tmp_name'], $caminhoArquivo)) {
                        throw new Exception("Não foi possível salvar o arquivo. {$file['name']} - {$nomeArquivo}");
                    }
                }

                $data = [
                    'id_processo' => $idProcesso,
                    'ds_observacao' => $observacao,
                    'ds_nome_arquivo' => $nomeArquivo,
                ];

                if (!$modelProcessosObservacoes->insert($data)) {
                    throw new Exception('Erro ao incluir a observação.');
                }

                $retorno['indiceLinhaSucesso'][] = $linha;

                Agro_Db_Table_Abstract::getDefaultAdapter()->commit();
            } catch (\Throwable $th) {
                Agro_Db_Table_Abstract::getDefaultAdapter()->rollback();

                if (!empty($caminhoArquivo) && file_exists($caminhoArquivo)) {
                    unlink($caminhoArquivo);
                }

                $retorno['erro'] = true;
                $retorno['propostasErro'][] = [
                    'idProposta' => $dados[0],
                    'indiceLinha' => $linha,
                    'erro' => $th->getMessage(),
                ];
            }
        }

        if ($retorno['erro']) {
            $retorno['mensagem'] = 'Nenhuma observação salva. Alguns erros foram encontrados.';
            if (!empty($retorno['indiceLinhaSucesso'])) {
                $retorno['mensagem'] = 'Observações salvas com sucesso. Porém, alguns erros foram encontrados.';
            }
        }

        $this->getResponse()->setBody(Zend_Json::encode($retorno));
    }

	public function preparadadosimportacoesAction()
	{
		$this->isAjax();
		$params = $this->getRequest()->getParams();

		try {
			if (empty($params['cbxTipo'])) {
				throw new Exception("Nenhum tipo informado.");
			}

			$Adapter = new Zend_File_Transfer_Adapter_Http();
			$Adapter->setDestination(APPLICATION_PATH.'/upload_files/temp/');
	
			$Adapter->addValidator('Extension', false, ["csv"]);
	
			if (!$Adapter->isValid()) {
				throw new Exception('Formato de arquivo inválido (formato(s) aceito(s): csv).');
			}
	
			$file = $Adapter->getFileInfo();
	
			if(!$Adapter->receive($file['arquivo']['name'])) {
				throw new Exception('Erro ao receber o arquivo de importação!');
			}
	
			$arquivo = fopen(APPLICATION_PATH.'/upload_files/temp/' . $file['arquivo']['name'],"r");

			switch ($params['cbxTipo']) {
				case '1':
					$retorno = $this->preparaRegistrosObservacao($arquivo);
					break;
				case '2':
					$retorno = $this->preparaRegistrosNovaAvaliacao($arquivo);
					break;
				case '3':
					$retorno = $this->preparaRegistrosRevisaoMaca($arquivo);
					break;
				default:
					throw new Exception("Tipo informado inválido.");
					break;
			}

			fclose($arquivo);
		} catch (\Throwable $th) {
			$retorno['mensagem'] = $th->getMessage();
			$retorno['erro'] = true;
		}
        
		$this->getResponse()->setBody(Zend_Json::encode($retorno));
        return true;
	}

	/**
	 * Valida se os dados informados na importação das observações da revisão da maçã possuem erros.
	 * 
	 * @param array $dados[
	 * 	0 => Proposta
	 *  1 => Itens
	 *  2 => Percentual de dano
	 *  3 => Fito
	 *  4 => Aguardando demais laudos
	 *  5 => Chamado vistoriador
	 *  6 => Chamado corretor
	 *  7 => Arquivo
	 * ]
	 * 
	 * @return array
	 */
	private function validarErrosRevisaoMaca(array $dados): array {
		$erros = [];
		$erroColunaProposta = false;
		
		if (empty($dados[0])) {
			$erros[] = 'Proposta não informada.';
			$erroColunaProposta = true;
		}

		if (empty($dados[1])) {
			$erros[] = 'Itens não informados.';
		}

		if ($dados[2] == "") {
			$erros[] = 'Percentual de dano não informado.';
		}

		$itens = explode(",", $dados[1]);
		$danos = explode("-", $dados[2]);

		if (count($itens) != count($danos)) {
			$erros[] = 'Quantidade de Itens diferente da quantidade de Percentual de Dano informado.';
		}

		if (empty($dados[3])) {
			$erros[] = 'Fito não informado.';
		} else {
			if (!in_array($dados[3], ['sim', 'não', 'sem cobertura'])) {
				$erros[] = 'Coluna Fito preenchido incorretamente. Somente os valores Sim, Não e Sem Cobertura são aceitos.';
			}
		}

		if (empty($dados[4])) {
			$erros[] = 'Aguardando demais laudos não informado.';
		} else {
			if (!in_array($dados[4], ['sim', 'não'])) {
				$erros[] = 'Coluna Aguardando demais laudos preenchido incorretamente. Somente os valores Sim e Não são aceitos.';
			}
		}

		if (empty($dados[5])) {
			$erros[] = 'Chamado vistoriador não informado.';
		} else {
			if (!in_array($dados[5], ['sim', 'não'])) {
				$erros[] = 'Coluna Chamado Vistoriador preenchido incorretamente. Somente os valores Sim e Não são aceitos.';
			}
		}

		if (empty($dados[6])) {
			$erros[] = 'Chamado corretor não informado.';
		} else {
			if (!in_array($dados[6], ['sim', 'não'])) {
				$erros[] = 'Coluna Chamado Corretor preenchido incorretamente. Somente os valores Sim e Não são aceitos.';
			}
		}

		if ($this->isNumeric($dados[0])) {
			$erros[] = 'Proposta deve conter somente valores numéricos.';
			$erroColunaProposta = true;
		}

		$idProcesso = "";
		if (!$erroColunaProposta) {
			$modelProcessos = new Sinistro2_Model_Processos();
			$idProcesso = $modelProcessos->getIdProcessoByProposta($dados[0]);
		
			if (empty($idProcesso)) {
				$erros[] = 'Processo não encontrado para a proposta informada.';
			}
		}

		return $erros;
	}

	private function preparaRegistrosRevisaoMaca($arquivo)
	{
		$retorno = ['erro' => false, 'mensagem' => ''];
		$totalLinhas = 0;
		
		while(($dados = fgetcsv($arquivo, 0, ";")) != false) {
			$totalLinhas++;

			if ($totalLinhas == 1) {
				if (count($dados) !== 8) {
					throw new Exception('Importação inválida. O arquivo deve conter 8 colunas com os cabeçalhos/dados.');
				}
				
				$dados[0] = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $dados[0]); //Remove caracter invisível do início da string
				$cabecalhoProposta = trim(strtolower($dados[0])) === 'proposta';
				$cabecalhoItens = trim(strtolower($dados[1])) === 'itens';
				$cabecalhoPercentualDano = trim(strtolower($dados[2])) === 'percentual de dano';
				$cabecalhoFito = trim(strtolower($dados[3])) === 'fito (sim, não ou sem cobertura)';
				$cabecalhoAguardandoDemaisLaudos = trim(strtolower($dados[4])) === 'aguardando demais laudos (sim ou não)';
				$cabecalhoChamadoVistoriador = trim(strtolower($dados[5])) === 'chamado vistoriador (sim ou não)';
				$cabecalhoChamadoCorretor = trim(strtolower($dados[6])) === 'chamado corretor (sim ou não)';
				$cabecalhoArquivo = trim(strtolower($dados[7])) === 'arquivo';

				if (!$cabecalhoProposta || !$cabecalhoItens || !$cabecalhoPercentualDano || !$cabecalhoFito || !$cabecalhoAguardandoDemaisLaudos || !$cabecalhoChamadoVistoriador || !$cabecalhoChamadoCorretor || !$cabecalhoArquivo) {
					throw new Exception('Cabeçalho do arquivo inválido. A primeira linha deve conter colunas com as seguintes descrições: Proposta, Itens, Percentual de dano, Fito (Sim, Não ou Sem cobertura), Aguardando demais laudos (Sim ou Não), Chamado Vistoriador (Sim ou Não), Chamado Corretor (Sim ou Não) e Arquivo.');
				}

				continue;
			}

			$dados[0] = trim($dados[0]); //Proposta
            $dados[1] = trim($dados[1]); //Itens
			
			$dados[2] = trim($dados[2]); //Percentual de dano
            
			$dados[3] = mb_strtolower(trim($dados[3]), "utf-8"); //Fito
            $dados[4] = mb_strtolower(trim($dados[4]), "utf-8"); //Aguardando demais laudos
            $dados[5] = mb_strtolower(trim($dados[5]), "utf-8"); //Chamado Vistoriador
            $dados[6] = mb_strtolower(trim($dados[6]), "utf-8"); //Chamado Corretor
            $dados[7] = trim($dados[7]); //arquivo

			$errosNaLinha = $this->validarErrosRevisaoMaca($dados);
			$retorno['erro'] = count($errosNaLinha) > 0;

			$registros[] = [
				'colunas' => [
					'id_proposta' => ['value' => $dados[0], 'type' => 'text', 'size' => '10', 'class' => 'integer meuinteger'],
					'itens' => ['value' => $dados[1], 'type' => 'text', 'size' => '10', 'class' => ''],
					'percentual_dano' => ['value' => $dados[2], 'type' => 'text', 'size' => '15', 'class' => ''],
					'fito' => ['value' => $dados[3], 'type' => 'select', 'options' => [['label' => 'Sim', 'value' => 'sim'], ['label' => 'Não', 'value' => 'não'], ['label' => 'Sem cobertura', 'value' => 'sem cobertura']], 'size' => '30', 'class' => ''],
					'aguardando_demais_laudos' => ['value' => $dados[4], 'type' => 'select', 'options' => [['label' => 'Sim', 'value' => 'sim'], ['label' => 'Não', 'value' => 'não']], 'size' => '30', 'class' => ''],
					'chamado_vistoriador' => ['value' => $dados[5], 'type' => 'select', 'options' => [['label' => 'Sim', 'value' => 'sim'], ['label' => 'Não', 'value' => 'não']], 'size' => '10', 'class' => ''],
					'chamado_corretor' => ['value' => $dados[6], 'type' => 'select', 'options' => [['label' => 'Sim', 'value' => 'sim'], ['label' => 'Não', 'value' => 'não']], 'size' => '30', 'class' => ''],
					'ds_nome_arquivo' => ['value' => $dados[7], 'type' => 'hidden', 'size' => '100', 'class' => ''],
				],
				'linha' => $totalLinhas,
				'erros' => $errosNaLinha
			];
		}

		$retorno['registros'] = $registros;
		return $retorno;
	}

	/**
	 * Valida se os dados informados na importação das novas avaliações possuem erros.
	 * 
	 * @param array $dados[
	 * 	0 => Proposta
	 *  1 => itens
	 *  2 => perito
	 *  3 => agronomo
	 *  4 => corretor
	 *  5 => observação
	 *  6 => arquivo
	 * ]
	 * 
	 * @return array
	 */
	private function validarErrosNovaAvaliacao(array $dados): array
	{
		$erros = [];
		$erroColunaProposta = false;

		if (empty($dados[0])) {
			$erros[] = "Proposta não informada.";
			$erroColunaProposta = true;
		}

		if (empty($dados[1])) {
			$erros[] = "Itens não informados.";
		}

		if (empty($dados[2])) {
			$erros[] = "Peritos não informados.";
		}

		if (empty($dados[4])) {
			$erros[] = "Corretor não informado.";
		} else {
			if (!in_array($dados[4], ['sim', 'não'])) {
				$erros[] = "Coluna Corretor preenchido incorretamente. Somente os valores Sim e Não são aceitos.";
			}
		}

		if ($this->isNumeric($dados[0])) {
			$erros[] = "Proposta deve conter somente valores numéricos.";
			$erroColunaProposta = true;
		}
		
		if (!$erroColunaProposta) {
			$modelProcessos = new Sinistro2_Model_Processos();
			$idProcesso = $modelProcessos->getIdProcessoByProposta($dados[0]);

			if (empty($idProcesso)) {
				$erros[] = "Processo não encontrado para a proposta informada.";
			}
		}
		return $erros;
	}

	/**
	 * Lê o arquivo de importação, aplica as validações necessárias e retorna um array com os erros e com os registros válidos.
	 * 
	 * @return array
	 */

	private function preparaRegistrosNovaAvaliacao($arquivo)
	{
		$retorno = ['erro' => false, 'mensagem' => ''];
		$totalLinhas = 0;
		
		while(($dados = fgetcsv($arquivo, 0, ";")) != false){
			$totalLinhas++;

			if ($totalLinhas == 1) {
				if (count($dados) !== 7) {
					throw new Exception('Importação inválida. O arquivo deve conter 7 colunas com os cabeçalhos/dados.');
				}
				
				$dados[0] = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $dados[0]); //Remove caracter invisível do início da string
				$cabecalhoProposta = trim(strtolower($dados[0])) === 'proposta';
				$cabecalhoItens = trim(strtolower($dados[1])) === 'itens';
				$cabecalhoPeritos = trim(strtolower($dados[2])) === 'peritos';
				$cabecalhoAgronomos = trim(strtolower($dados[3])) === 'agrônomos';
				$cabecalhoCorretor = trim(strtolower($dados[4])) === 'corretor (sim ou não)';
				$cabecalhoObservacao = trim(strtolower($dados[5])) === 'observação';
				$cabecalhoArquivo = trim(strtolower($dados[6])) === 'arquivo';

				if (!$cabecalhoProposta || !$cabecalhoItens || !$cabecalhoPeritos || !$cabecalhoAgronomos || !$cabecalhoCorretor || !$cabecalhoObservacao || !$cabecalhoArquivo) {
					throw new Exception('Cabeçalho do arquivo inválido. A primeira linha deve conter colunas com as seguintes descrições: Proposta, Itens, Peritos, Agrônomos, Corretor (Sim ou Não), Observação e Arquivo');
				}

				continue;
			}

            $dados[0] = trim($dados[0]); //proposta
            $dados[1] = trim($dados[1]); //itens
            $dados[2] = trim($dados[2]); //perito
            $dados[3] = trim($dados[3]); //agronomo
            $dados[4] = mb_strtolower(trim($dados[4]), "utf-8"); //corretor
            $dados[5] = trim($dados[5]); //observacao
            $dados[6] = trim($dados[6]); //arquivo

			$errosNaLinha = $this->validarErrosNovaAvaliacao($dados);
			$retorno['erro'] = count($errosNaLinha) > 0;

			$registros[] = [
				'colunas' => [
					'id_proposta' => ['value' => $dados[0], 'type' => 'text', 'size' => '10', 'class' => 'integer meuinteger'],
					'itens' => ['value' => $dados[1], 'type' => 'text', 'size' => '10', 'class' => ''],
					'peritos' => ['value' => $dados[2], 'type' => 'text', 'size' => '30', 'class' => ''],
					'agronomos' => ['value' => $dados[3], 'type' => 'text', 'size' => '30', 'class' => ''],
					'corretor' => ['value' => $dados[4], 'type' => 'select', 'options' => [['label' => 'Sim', 'value' => 'sim'], ['label' => 'Não', 'value' => 'não']], 'size' => '10', 'class' => ''],
					'observacoes' => ['value' => $dados[5], 'type' => 'text', 'size' => '30', 'class' => ''],
					'ds_nome_arquivo' => ['value' => $dados[6], 'type' => 'hidden', 'size' => '100', 'class' => ''],
				],
				'linha' => $totalLinhas,
				'erros' => $errosNaLinha
			];
		}

		$retorno['registros'] = $registros;
		return $retorno;
	}

	private function isNumeric($valor)
	{
		$expressao = '/[^0-9]/';
		return preg_match($expressao, $valor);
	}

	/**
	 * Valida se os dados informados na importação das observações do processo possuem erros.
	 * 
	 * @param array $dados[
	 * 	0 => Proposta
	 *  1 => Observação
	 *  2 => Arquivo
	 * ]
	 * 
	 * @return array
	 */
	private function validarErrosObservacao(array $dados): array
	{
		$erros = [];

		if (empty($dados[0])) {
			$erros[] = 'Proposta não informada.';
			$erroColunaProposta = true;
		}

		if (empty($dados[1])) {
			$erros[] = 'Observação não informada.';
		}

		if ($this->isNumeric($dados[0])) {
			$erros[] = 'Proposta deve conter somente valores numéricos.';
			$erroColunaProposta = true;
		}

		if (!$erroColunaProposta) {
			$modelProcessos = new Sinistro2_Model_Processos();
			$idProcesso = $modelProcessos->getIdProcessoPropostaVigenteByProposta($dados[0]);

			if (empty($idProcesso)) {
				$erros[] = 'Processo não encontrado para a proposta informada.';
			}
		}
		return $erros;
	}
	
	/**
	 * Lê o arquivo de importação, aplica as validações necessárias e retorna um array com os erros e com os registros válidos.
	 * 
	 * @return array
	 */
	private function preparaRegistrosObservacao($arquivo): array
	{
		$retorno = ['erro' => false, 'mensagem' => ''];
		$totalLinhas = 0;
		
		while(($dados = fgetcsv($arquivo, 0, ";")) != false){
			$totalLinhas++;

			if ($totalLinhas == 1) {
				if (count($dados) !== 3) {
					throw new Exception('Importação inválida. O arquivo deve conter 3 colunas com os cabeçalhos/dados.');
				}
				
				$dados[0] = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $dados[0]); //Remove caracter invisível do início da string
				$cabecalhoProposta = trim(strtolower($dados[0])) === 'proposta';
				$cabecalhoObservacao = trim(strtolower($dados[1])) === 'observação';
				$cabecalhoArquivo = trim(strtolower($dados[2])) === 'arquivo';

				if (!$cabecalhoProposta || !$cabecalhoObservacao || !$cabecalhoArquivo) {
					throw new Exception('Cabeçalho do arquivo inválido. A primeira linha deve conter colunas com as seguintes descrições: Proposta, Observação e Arquivo.');
				}

				continue;
			}

            $dados[0] = trim($dados[0]); //proposta
            $dados[1] = trim($dados[1]); //observacao
            $dados[2] = trim($dados[2]); //arquivo

			$errosNaLinha = $this->validarErrosObservacao($dados);
			$retorno['erro'] = count($errosNaLinha) > 0;

            $registros[] = [
				'colunas' => [
					'id_proposta' => ['value' => $dados[0], 'type' => 'text', 'size' => '10', 'class' => 'integer meuinteger'],
					'ds_observacao' => ['value' => $dados[1], 'type' => 'text', 'size' => '100', 'class' => ''],
					'ds_nome_arquivo' => ['value' => $dados[2], 'type' => 'hidden', 'size' => '100', 'class' => ''],
				],
				'linha' => $totalLinhas,
				'erros' => $errosNaLinha
			];
		}

		$retorno['registros'] = $registros;
		return $retorno;
	}

    public function importaobservacoesarquivoAction()
    {

        $this->isAjax();
        Agro_Db_Table_Abstract::getDefaultAdapter()->beginTransaction();

        $Adapter = new Zend_File_Transfer_Adapter_Http();
        $Adapter->setDestination(APPLICATION_PATH . '/upload_files/temp/');
        $file = $Adapter->getFileInfo();

        if (!$Adapter->receive($file['file']['name'])) {
            $alert = 'Erro ao importar Observações!';
            $result = 0;
        } else {

            $extensao = explode('.', $file['file']['name']);

            if (end($extensao) == 'csv') {
                //abre o arquivo
                $arquivo = fopen(APPLICATION_PATH . '/upload_files/temp/' . $file['file']['name'], "r");
                $Model = $this->getModel();

                $linha = 0;
                $result = 1;
                //processa o csv
                while (($dados = fgetcsv($arquivo, 0, ";")) != false && $result != 0) {
                    $data[$linha]['nota'] = utf8_encode($dados[0]);
                    $data[$linha]['proposta'] = utf8_encode($dados[1]);
                    $data[$linha]['tipo_laudo'] = utf8_encode($dados[2]);
                    $data[$linha]['quadra'] = utf8_encode($dados[3]);
                    $data[$linha]['variedade'] = utf8_encode($dados[4]);
                    $data[$linha]['sinistro'] = utf8_encode($dados[5]);
                    $data[$linha]['data'] = utf8_encode($dados[6]);

                    try {
                        //pula a primeira linha pois é cabeçalho
                        if ($linha != 0) {
                            $Processos = new Sinistro2_Model_Processos();

                            $id_processo = $Processos->getIdProcessoByProposta($data[$linha]['proposta']);
                            if (!$id_processo) {
                                $alert = 'Proposta  ' . $data[$linha]['proposta'] . ' na linha ' . ($linha + 1) . ' não possui processo! Importação cancelada!';
                                $result = 0;

                            } else {
                                $data[$linha]['id_processo'] = $id_processo;
                                $Model->save($data[$linha]);

                                $alert = 'Observações de Processos importadas com sucesso!';
                                $result = 1;

                            }
                        }
                    } catch (Exception $e) {

                        Agro_Db_Table_Abstract::getDefaultAdapter()->rollback();

                        $linha++;
                        $alert = "Erro ao importar Observações! Informações da linha $linha inválidas!";
                        $result = 0;
                    }
                    $linha++;
                }

                fclose($arquivo);

                Agro_Db_Table_Abstract::getDefaultAdapter()->commit();

            } else {

                $alert = 'Formato de arquivo inválido!';
                $result = 0;
            }
        }

        $this->getResponse()->setBody(
            "<script>window.top.window.stopUpload($result);
				alert(\"$alert\");
			</script>"
        );

    }

    public function importareservasarquivoAction()
    {
        $this->isAjax();
        //Agro_Db_Table_Abstract::getDefaultAdapter()->beginTransaction();

        $Adapter = new Zend_File_Transfer_Adapter_Http();
        $Adapter->setDestination(APPLICATION_PATH . '/upload_files/temp/');
        $file = each($Adapter->getFileInfo());
        $modelUsuarios = new Sistema_Model_Usuarios();
        $Propostas = new Seguro_Model_Propostas();
        $Model = $this->getModel();
        $User = Zend_Auth::getInstance()->getIdentity();

        if (!$Adapter->receive()) {
            $alert = 'Erro ao importar Reservas!';
            $return = 0;
        } else {

            $extensao = explode('.', $file[1]['name']);

            if (end($extensao) == Agro_File::CSV_EXTENSION) {
                //abre o arquivo
                $arquivo = fopen(APPLICATION_PATH . '/upload_files/temp/' . $file[1]['name'], "r");
                $linha = 0;
                $return = 1;
                //para saber quantos restar e sinalizar o final no rabbitmq consumidor
                $restando = count(file(APPLICATION_PATH . '/upload_files/temp/' . $file[1]['name']));

                //processa o csv
                while (($dados = fgetcsv($arquivo, 0, ";")) != false && $return != 0) {

                    if (!is_numeric($dados[0])) {
                        $restando--;
                        continue;
                    }

                    $data[$linha]['proposta'] = utf8_encode($dados[0]);
                    $data[$linha]['apolice'] = utf8_encode($dados[1]);
                    $data[$linha]['aviso'] = utf8_encode($dados[2]);
                    $data[$linha]['cobertura'] = utf8_encode($dados[3]);
                    $data[$linha]['valor'] = utf8_encode($dados[4]);
		            $data[$linha]['tipo'] = utf8_encode($dados[5]);
		            $data[$linha]['id_usuario_alteracao'] = $User->id;
                    $data[$linha]['restando'] = $restando - $linha - 1;

                    try {
                        if ($data[$linha]['restando'] == 0) {
                            //Ids dos usuarios marcia.correa, rafael.silva, tatiana.tondim e tiago.zschornack
                            $data[$linha]['usuarios_sinistro_notificados'] = [1060,3887,1854,2503];
                        }

                        $clt = new Agro_RabbitMQ_RcpClient(APPLICATION_ENV);
                        $mysoapmsg = $this->montaXMLTransmissao($data[$linha]['aviso'], $data[$linha]['valor'], $data[$linha]['tipo']);

                        $clt->execute($mysoapmsg, $data[$linha]);
                    } catch (Exception $e) {
                        $linha++;
                        $alert = "Erro ao importar Reservas (2)! Informações da linha $linha inválidas!";
                        $return = 0;
                    }
                    $linha++;
                }

                fclose($arquivo);

                if ($return == 1) {
                    $alert = 'Reservas ajustadas com sucesso!';
                }

            } else {
                $alert = 'Formato de arquivo inválido!';
                $return = 0;
            }
        }

        $this->getResponse()->setBody(
            "<script>window.top.window.stopUpload($return);
				alert(\"$alert\");
				</script>"
        );
    }

    public function atualizarreservasAction()
    {

        $this->isAjax();
        Agro_Db_Table_Abstract::getDefaultAdapter()->beginTransaction();

        $Adapter = new Zend_File_Transfer_Adapter_Http();
        $Adapter->setDestination(APPLICATION_PATH . '/upload_files/temp/');
        $file = $Adapter->getFileInfo();

        $User = Zend_Auth::getInstance()->getIdentity();

        if (!$Adapter->receive($file['file_reservas']['name'])) {
            $alert = 'Erro ao atualizar Reservas!';
            $return = 0;
        } else {

            $extensao = explode('.', $file['file_reservas']['name']);

            if (end($extensao) == 'csv') {
                //abre o arquivo
                $arquivo = fopen(APPLICATION_PATH . '/upload_files/temp/' . $file['file_reservas']['name'], "r");
                $linha = 0;
                $return = 1;

                //processa o csv
                while (($dados = fgetcsv($arquivo, 0, ";")) != false && $return != 0) {

                    $data[$linha]['cd_identificador_seguradora'] = utf8_encode($dados[0]);
                    $data[$linha]['valor'] = utf8_encode($dados[1]);

                    try {
                        //pula a primeira linha pois é cabeçalho
                        if ($linha != 0) {
                            $AvisosTransmissao = new Sinistro2_Model_AvisosTransmissaoSeguradora();
                            $AvisosTransmissao->update(array('vl_reserva' => $data[$linha]['valor'], 'dt_alteracao' => 'now()', 'id_usuario_alteracao' => $User->id), "cd_identificador_seguradora = '{$data[$linha]['cd_identificador_seguradora']}'");
                        }
                    } catch (Exception $e) {
                        Agro_Db_Table_Abstract::getDefaultAdapter()->rollback();
                        $linha++;
                        $alert = "Erro ao atualizar Reservas! Informações da linha $linha inválidas!";
                        $return = 0;
                    }
                    $linha++;

                }

                fclose($arquivo);

                if ($return == 1) {
                    $alert = 'Reservas atualizadas com sucesso!';
                    Agro_Db_Table_Abstract::getDefaultAdapter()->commit();
                }

            } else {
                $alert = 'Formato de arquivo inválido!';
                $return = 0;
            }
        }

        $this->getResponse()->setBody(Zend_Json::encode($alert));
    }

    public function atualizarindenizacoesAction()
    {

        $this->isAjax();
        Agro_Db_Table_Abstract::getDefaultAdapter()->beginTransaction();

        $Adapter = new Zend_File_Transfer_Adapter_Http();
        $Adapter->setDestination(APPLICATION_PATH . '/upload_files/temp/');
        $file = $Adapter->getFileInfo();

        $User = Zend_Auth::getInstance()->getIdentity();

        if (!$Adapter->receive($file['file_indenizacoes']['name'])) {
            $alert = 'Erro ao atualizar Indenizações!';
            $return = 0;
        } else {

            $extensao = explode('.', $file['file_indenizacoes']['name']);

            if (end($extensao) == 'csv') {
                //abre o arquivo
                $arquivo = fopen(APPLICATION_PATH . '/upload_files/temp/' . $file['file_indenizacoes']['name'], "r");
                $linha = 0;
                $return = 1;

                //processa o csv
                while (($dados = fgetcsv($arquivo, 0, ";")) != false && $return != 0) {
                    $data[$linha]['cd_identificador_seguradora'] = utf8_encode($dados[0]);
                    $data[$linha]['valor'] = utf8_encode($dados[1]);

                    try {
                        //pula a primeira linha pois é cabeçalho
                        if ($linha != 0) {
                            $AvisosTransmissao = new Sinistro2_Model_AvisosTransmissaoSeguradora();
                            $AvisosTransmissao->update(array('vl_indenizacao' => $data[$linha]['valor'], 'dt_alteracao' => 'now()', 'id_usuario_alteracao' => $User->id), "cd_identificador_seguradora = '{$data[$linha]['cd_identificador_seguradora']}'");
                        }
                    } catch (Exception $e) {
                        Agro_Db_Table_Abstract::getDefaultAdapter()->rollback();
                        $linha++;
                        $alert = "Erro ao atualizar Indenizações! Informações da linha $linha inválidas!";
                        $return = 0;
                    }
                    $linha++;
                }

                fclose($arquivo);

                if ($return == 1) {
                    $alert = 'Indenizações atualizadas com sucesso!';
                    Agro_Db_Table_Abstract::getDefaultAdapter()->commit();
                }

            } else {
                $alert = 'Formato de arquivo inválido!';
                $return = 0;
            }
        }

        $this->getResponse()->setBody(Zend_Json::encode($alert));
    }

    public function montaXMLTransmissao($id_aviso, $valor, $tipo)
    {
        $model = $this->getModel();
        $rsAviso = $model->getDadosTransmissaoXML($id_aviso);

        if (empty($rsAviso)) {
            throw new Exception("Não foi possível recuperar os dados do log de transmissão do aviso {$id_aviso}.");
        }
        
        $modelPropostas = new Seguro_Model_Propostas();
        $proposta = $modelPropostas->find($rsAviso['id_proposta'])->current();
        $proponente = $proposta->proponente();

        $cpf_cnpj_sinistrada = str_replace('.', '', str_replace('/', '', str_replace('-', '', $proponente['cpf_cnpj'])));
        if ($proponente['tp_pessoa'] == 'F') {
            $tp_pessoa_sinistrada = 1;
        } else {
            $tp_pessoa_sinistrada = 2;
        }

        $tipoMovimento = '';

        switch ($tipo) {
            case 'AJUSTE_MAIS':
                $idTipoAjuste = 10102;
                break;
            case 'AJUSTE_MENOS':
                $idTipoAjuste = 10104;
                break;
            case 'CANCELAMENTO':
                $idTipoAjuste = 10105;
                $tipoMovimento = 17;
                break;
        }

        $xml = "
		<i4proerp>
			<insereMovimentoSinistroRural>
				<insereMovimento>
					<apolice>" . $proposta->nr_apolice . "</apolice>
					<dtMovimento></dtMovimento>
					<endosso>" . $proposta->ds_identificador_seguradora . "</endosso>
					<sinistro>" . $rsAviso['cd_identificador_seguradora'] . "</sinistro>
					<evento>" . $idTipoAjuste . "</evento>
					<cobertura>" . $rsAviso['cobertura_xml'] . "</cobertura>
					<valorOperacao>" . $valor . "</valorOperacao>
					<observacao>Ajuste de Reserva</observacao>
					<tipoMovimento>{$tipoMovimento}</tipoMovimento>
					<nomeFavorecido>" . $proponente['ds_nome_proponente'] . "</nomeFavorecido>
					<tipoPessoaFavorecido>" . $tp_pessoa_sinistrada . "</tipoPessoaFavorecido>
					<nrCnpjCpfFavorecido>" . $cpf_cnpj_sinistrada . "</nrCnpjCpfFavorecido>
					<dtNascimentoFavorecido>1980-01-01</dtNascimentoFavorecido>
					<sexoFavorecido>1</sexoFavorecido>
					<nrDocumentoFavorecido>" . $cpf_cnpj_sinistrada . "</nrDocumentoFavorecido>
					<dtAgendamento></dtAgendamento> 
					<nrCi></nrCi> 
					<ajusta></ajusta> 
					<descontaPremioPendente></descontaPremioPendente> 
					<liberaConsistencias>1</liberaConsistencias>
					<tributaIndenizacao>0</tributaIndenizacao>
					<meioPagamento></meioPagamento>
					<nrBanco></nrBanco>
					<nrAgencia></nrAgencia>
					<nrDacAgencia></nrDacAgencia>
					<nrContaCorrente></nrContaCorrente>
					<nrDacContaCorrente></nrDacContaCorrente>
					<nrCheque></nrCheque>
					<nrEventoSequenciaEstorno></nrEventoSequenciaEstorno>
					<tipoDocumento></tipoDocumento>
					<serieDocumento></serieDocumento>
					<nrDocumento></nrDocumento>
					<dtNotaFiscal></dtNotaFiscal>
					<encerraSinistro>0</encerraSinistro>
				</insereMovimento>
			</insereMovimentoSinistroRural>
		</i4proerp>";

        return $xml;
    }


    public function desabilitarlaudosarquivoAction()
    {

        $this->isAjax();
        Agro_Db_Table_Abstract::getDefaultAdapter()->beginTransaction();

        $Adapter = new Zend_File_Transfer_Adapter_Http();
        $Adapter->setDestination(APPLICATION_PATH . '/upload_files/temp/');
        $file = $Adapter->getFileInfo();

        if (!$Adapter->receive($file['file']['name'])) {
            $alert = 'Erro ao desabilitar Laudos Preliminares!';
            $result = 0;
        } else {

            $extensao = explode('.', $file['file']['name']);

            if (end($extensao) == 'csv') {
                //abre o arquivo
                $arquivo = fopen(APPLICATION_PATH . '/upload_files/temp/' . $file['file']['name'], "r");
                $Model = $this->getModel();

                $linha = 0;
                $result = 1;

                $Model = new Sinistro2_Model_AvisosSinistro();

                //processa o csv
                while (($dados = fgetcsv($arquivo, 0, ";")) != false && $result != 0) {
                    $id_aviso = $dados[0];

                    try {
                        //pula a primeira linha pois é cabeçalho
                        if ($linha != 0) {
                            $Aviso = $Model->find($id_aviso)->current();
                            $Aviso->fl_dispensa_preliminar = true;
                            $Aviso->save();

                            $alert = 'Ok';
                        }

                    } catch (Exception $e) {
                        Agro_Db_Table_Abstract::getDefaultAdapter()->rollback();
                        $linha++;
                        $alert = "Erro ao desabilitar Laudos Preliminares! Informações da linha $linha inválidas!";
                        $result = 0;
                    }
                    $linha++;
                }

                fclose($arquivo);

                Agro_Db_Table_Abstract::getDefaultAdapter()->commit();

            } else {

                $alert = 'Formato de arquivo inválido!';
                $result = 0;
            }
        }

        $this->getResponse()->setBody(
            "<script>window.top.window.stopUpload($result);
				alert(\"$alert\");
			</script>"
        );

    }

    public function cobraragendamentosvistoriasAction()
    {
        $this->getHelper('ViewRenderer')->setNoRender();
        $this->getHelper('layout')->disableLayout();

        if (
            $this->getRequest()->getParam('agendamentoVP') ||
            $this->getRequest()->getParam('agendamentoVPL') ||
            $this->getRequest()->getParam('agendamentoVF') ||
            $this->getRequest()->getParam('digitacaoVP') ||
            $this->getRequest()->getParam('digitacaoVPL') ||
            $this->getRequest()->getParam('digitacaoVF')
        ) {
            Agro_Db_Table_Abstract::getDefaultAdapter()->beginTransaction();

            $result['status'] = 'Processo executado com sucesso!';

            Agro_Db_Table_Abstract::getDefaultAdapter()->commit();
        } else {
            $result['status'] = 'Selecione ao menos alguma opção de Cobrança!';
        }
        $this->getResponse()->setBody(Zend_Json::encode($result));
    }

    public function geraSalvaXml($nomeArquivo, $msg)
    {
        $file = fopen(APPLICATION_PATH . "/upload_files/xml_transmissao_error/{$nomeArquivo}", "w+");
        fwrite($file, $msg);
        fclose($file);
    }

    public function indeximportaridreciboAction()
    {
        parent::indexAction();
        $this->view->title = 'Sinistro » Rotinas » Importar IDs de Recibos';
    }

    public function importaridreciboAction()
    {
        $this->isAjax();

        $retorno = ['erro' => false, 'mensagem' => 'Importação realizada com sucesso.', 'erros' => []];
        $registros = [];

        $adapter = new Zend_File_Transfer_Adapter_Http();
        $adapter->setDestination(APPLICATION_PATH . '/upload_files/temp/');
        $adapter->addValidator('Extension', false, ['csv']);

        $file = $adapter->getFileInfo();
        $nomeArquivo = $file['id_recibos']['name'];

        if (!$adapter->isValid()) {
            $retorno['erro'] = true;
            $retorno['mensagem'] = 'Formato de arquivo inválido (formato aceito: .csv).';

            $this->getResponse()->setBody(Zend_Json::encode($retorno));

            return false;
        }

        if (!$adapter->receive($nomeArquivo)) {
            $retorno['erro'] = true;
            $retorno['mensagem'] = 'Erro ao receber o arquivo de importação dos IDs do recibo.';

            $this->getResponse()->setBody(Zend_Json::encode($retorno));

            return false;
        }

        $arquivo = fopen(APPLICATION_PATH . '/upload_files/temp/' . $nomeArquivo, 'r');
        $liquidacoesDuplicadas = array();

        $idsLiquidacoes = [];
      
        while (($dados = fgetcsv($arquivo, 0, ';')) != false) {
            if (count($dados) !== 5) {
                $mensagem = "Importação inválida. O arquivo deve conter 5 colunas com o cabeçalho (não obrigatório)/dados na seguinte ordem:";
                $mensagem .= "\n1ª - id_recibo";
                $mensagem .= "\n2ª - id_liquidacao";
                $mensagem .= "\n3ª - id_pagamento";
                $mensagem .= "\n4ª - dt_pagamento";
                $mensagem .= "\n5ª - vl_pagamento";

                $retorno['erro'] = true;
                $retorno['mensagem'] = $mensagem;

                $this->getResponse()->setBody(Zend_Json::encode($retorno));

                return false;
            }
           
            $expressao = '/[^0-9]/';
            $recibo = trim($dados[0]);
            $liquidacao = trim($dados[1]);
            $idPagamento = trim($dados[2]);
            $dataPagamento = trim($dados[3]);
            $valorPagamento = trim($dados[4]);

            $stdErro = (object) [
                'id_recibo_seguradora' => $recibo,
                'id_liquidacao' => $liquidacao,
                'id_pagamento_seguradora' => $idPagamento,
                'dt_pagamento' => $dataPagamento,
                'vl_pagamento' => $valorPagamento,
                'erro' => ''
            ];
            
            if (
                $recibo === 'id_recibo'
                || $liquidacao === 'id_liquidacao'
                || $idPagamento === 'id_pagamento'
                || $dataPagamento === 'dt_pagamento'
                || $valorPagamento === 'vl_pagamento'
            ) {
                continue;
            }

            if (
                preg_match($expressao, $recibo)
                || preg_match($expressao, $liquidacao)
                || preg_match($expressao, $idPagamento)
            ) {
                $retorno['erro'] = true;
                $stdErro->erro = 'ID Recibo, ID Liquidação e/ou ID Pagamento inválido(s) (conter somente valor numérico).';
                $retorno['erros'][] = $stdErro;
                continue;
            }

            if (
                empty($recibo)
                || empty($liquidacao)
                || empty($idPagamento)
                || empty($dataPagamento)
                || empty($valorPagamento)
            ) {
                $retorno['erro'] = true;
                $stdErro->erro = 'ID Recibo, ID Liquidação, ID Pagamento, Data de Pagamento e/ou Valor de Pagamento não informado(s).';
                $retorno['erros'][] = $stdErro;
                continue;
            }

            if (
                !preg_match('/^([0-2][0-9]|(3)[0-1])(\/)(((0)[0-9])|((1)[0-2]))(\/)\d{4}$/', $dataPagamento)
                && !preg_match('/^([0-2][0-9]|(3)[0-1])(\-)(((0)[0-9])|((1)[0-2]))(\-)\d{4}$/', $dataPagamento)
            ) {
                $retorno['erro'] = true;
                $stdErro->erro = 'Data de Pagamento está no formato errado. A data deve estar conforme os exemplos: 10/01/2021 ou 10-01-2021.';
                $retorno['erros'][] = $stdErro;
                continue;
            }

            if (!is_numeric($valorPagamento)) {
                $retorno['erro'] = true;
                $stdErro->erro = 'Valor de Pagamento está no formato errado. O valor deve estar conforme o exemplo: 800.00';
                $retorno['erros'][] = $stdErro;
                continue;
            }

            if (
                array_key_exists($liquidacao, $liquidacoesDuplicadas) ||
                (array_key_exists($liquidacao, $registros) && $registros[$liquidacao]['id_recibo_seguradora'] != $recibo)
            ) {

                if (!array_key_exists($liquidacao, $liquidacoesDuplicadas)) {
                    $liquidacoesDuplicadas[$liquidacao] = $liquidacao;

                    $retorno['erro'] = true;
                    $stdErro->erro = "O recibo da liquidação {$liquidacao} não foi importado pois ela possui mais de um recibo.";
                    $retorno['erros'][] = $stdErro;
                }

                unset($registros[$liquidacao]);
                continue;
            }

            $idsLiquidacoes[] = $liquidacao;
            
            $ModelLiquidacoesISC = new Sinistro2_Model_LiquidacoesItensSeguradosCoberturas();
            $totalItensSegurados = $ModelLiquidacoesISC->fetchAll("id_liquidacao={$liquidacao}")->count();

            if (empty($totalItensSegurados)) {
                $retorno['erro'] = true;
                $stdErro->erro = "A liquidação {$liquidacao} não possui itens segurados vinculados a ela. Favor entrar em contato com a AgroBrasil Seguros.";
                $retorno['erros'][] = $stdErro;
                continue;
            }

            $registros[$liquidacao] = [
                'id_recibo_seguradora' => $recibo,
                'id_liquidacao' => $liquidacao,
                'id_pagamento_seguradora' => $idPagamento,
                'dt_confirmacao_pagamento' => $dataPagamento,
                'vl_pagamento' => $valorPagamento
            ];
        }
        
        fclose($arquivo);
        
        $modelLiquidacoesPrevisaoPagamento = new Sinistro2_Model_LiquidacoesPrevisaoPagamento();
        $modelLiquidacaoPagamentoAdicional = new Sinistro2_Model_LiquidacaoPagamentoAdicional();
        $modelStatus = new Sistema_Model_Status();
        $modelLiquidacao = new Sinistro2_Model_Liquidacoes();

        $mapIdsLiquidacoesImportados = $modelLiquidacoesPrevisaoPagamento
            ->getMapIdsLiquidacoesImportados($idsLiquidacoes);
        $mapIdsLiquidacoesPrevisaoPagamento = $modelLiquidacoesPrevisaoPagamento
            ->getMapPrevisoesPagamentoByIdsLiquidacoes($idsLiquidacoes);
        $mapIdsLiquidacoesStatus = $modelLiquidacao->getMapIdsLiquidacoesStatus($idsLiquidacoes);
        $mapIdsLiquidacoesPagamentoAdicional = $modelLiquidacaoPagamentoAdicional
            ->getMapIdsLiquidacoesPagamentoAdicional($idsLiquidacoes);
        
        $retorno['arquivoJaImportado'] = false;

        $idStatusAguardandoPagamento = $modelStatus->getIdStatus('AGUARDANDO_PAGAMENTO', 'LIQUIDACOES');
        $idStatusIndenizacaoPaga = $modelStatus->getIdStatus('INDENIZACAO_PAGA', 'LIQUIDACOES');

        $idStatusAguardandoPagamentoPagamentoAdicional = $modelStatus->getIdStatus(
            'AGUARDANDO_PAGAMENTO',
            'LIQUIDACAO_PAGAMENTO_ADICIONAL'
        );
        
        foreach ($registros as $key => $registro) {
            if (array_key_exists($registro['id_liquidacao'], $mapIdsLiquidacoesImportados) ) {
                
                /**
                 * Uma mesma liquidação pode ter recibos diferentes importados
                 * Um para a liquidação em si e outra para o pagamento adicional
                 */
                foreach ($mapIdsLiquidacoesImportados[$registro['id_liquidacao']] as $previsaoPagamento) {
                    if ($previsaoPagamento->id_recibo_seguradora == $registro['id_recibo_seguradora']) {
                        $retorno['arquivoJaImportado'] = true;
                        $retorno['erro'] = true;
                        $retorno['mensagem'] = 'Verifique o arquivo, os recibos já foram importados anteriormente.';
                    }
                }
            }

            $pagamentoAdicional = $mapIdsLiquidacoesPagamentoAdicional[$registro['id_liquidacao']] ?? null;
            
            /**
             * Se for importação de recibo de pagamento adicional o status da liquidação vai estar como INDENIZAÇÃO PAGA
             * O será importado para este pagamento adicional caso o status dele esteja como AGUARDANDO PAGAMENTO
             */
            if (
                !in_array(
                    $mapIdsLiquidacoesStatus[$registro['id_liquidacao']],
                    [$idStatusAguardandoPagamento, $idStatusIndenizacaoPaga]
                )
                || (
                    $mapIdsLiquidacoesStatus[$registro['id_liquidacao']] == $idStatusIndenizacaoPaga
                    && array_key_exists($registro['id_liquidacao'], $mapIdsLiquidacoesPagamentoAdicional)
                    && $pagamentoAdicional['id_status'] != $idStatusAguardandoPagamentoPagamentoAdicional
                )
            ) {
                unset($registros[$key]);
                continue;
            }


            $registros[$key]['fl_pagamento_adicional'] = $mapIdsLiquidacoesStatus[$registro['id_liquidacao']] == $idStatusIndenizacaoPaga
                && !is_null($pagamentoAdicional)
                && $pagamentoAdicional['id_status'] == $idStatusAguardandoPagamentoPagamentoAdicional;
        }
        
        if (!$retorno['arquivoJaImportado']) {
            $idStatusIndenizacaoPagaPagamentoAdicional = $modelStatus
                ->getId('INDENIZACAO_PAGA', 'LIQUIDACAO_PAGAMENTO_ADICIONAL');
            
            foreach ($registros as $key => $registro) {
                Agro_Db_Table_Abstract::getDefaultAdapter()->beginTransaction();

                $previsaoPagamento = $registro;
                
                // Se não for pagamento adicional, atualiza pagamento existente
                if (
                    !empty($mapIdsLiquidacoesPrevisaoPagamento[$registro['id_liquidacao']]) 
                    && !$registro['fl_pagamento_adicional']
                ) {
                    $previsaoPagamento['id'] = $mapIdsLiquidacoesPrevisaoPagamento[$registro['id_liquidacao']]['id'];
                }
                
                try {
                    $modelLiquidacoesPrevisaoPagamento->save($previsaoPagamento);
                    
                    // Salva pagamento adicional
                    $pagamentoAdicional = null;
                    if ($registro['fl_pagamento_adicional']) {
                        $modelLiquidacoesPrevisaoPagamento->save($registro);
                        $pagamentoAdicional = $mapIdsLiquidacoesPagamentoAdicional[$registro['id_liquidacao']] ?? null;
                        
                        if (!empty($pagamentoAdicional) && $pagamentoAdicional['id_status'] == $idStatusAguardandoPagamentoPagamentoAdicional) {
                            $pagamentoAdicional['id_status'] = $idStatusIndenizacaoPagaPagamentoAdicional;
                            $modelLiquidacaoPagamentoAdicional->salvar($pagamentoAdicional);
                        }
                    }
                    
                    //ATUALIZAÇÃO DO STATUS SE POSSUI INDENIZAÇÃO
                    $Liquidacao = $modelLiquidacao->find($registro['id_liquidacao'])->current();

                    if ($modelStatus->getChave($Liquidacao->id_status) != 'SEM_INDENIZACAO') {
                        $modelLiquidacao->atualizaStatusLiquidacao(
                            $registro['id_liquidacao'],
                            $modelStatus->getIdStatus('INDENIZACAO_PAGA', 'LIQUIDACOES')
                        );
                    }
                    
                    Agro_Db_Table_Abstract::getDefaultAdapter()->commit();
                } catch (Exception $erro) {
                    $registro['erro'] = "Liquidação inexistente no sitema.";

                    $retorno['erro'] = true;
                    $retorno['erros'][] = $registro;

                    Agro_Db_Table_Abstract::getDefaultAdapter()->rollback();
                }
                
                try {
                    $id_proposta = (new Sinistro2_Model_Processos())->find($Liquidacao->id_processo)->current()->id_proposta;
                    $command = "/usr/bin/python3 " . $_SERVER['DOCUMENT_ROOT'] . "/../rabbitmq/send_mail.py " . $id_proposta . ' ' . $registro['id_liquidacao'];
                    exec($command, $op, $hup);
                    $retorno['erro'] = false;

                } catch (Exception $e) {
                    $retorno['erro'] = true;
                }
            }
            
            if ($retorno['erro'] === true) {
                $retorno['mensagem'] = 'Importação realizada com sucesso. Algumas linhas não foram importadas, sendo o motivo';
                $retorno['mensagem'] .= ' apresentado na tela.';
            }
        }

        $this->getResponse()->setBody(Zend_Json::encode($retorno));

        return true;
    }
    
    public function importarlaudoxmlAction()
    {
        $this->getHelper('layout')->setLayout('popup');
        $this->view->title = 'Sinistro » Rotinas » Importação de Laudos de Vistoria';
        $this->view->form = $this->getForm();

        $this->view->nomeArquivo = (new Seguro_Model_PropostasCroquis())->getNomeArquivoCroqui(
            $this->getRequest()->getParam('id_proposta')
        );

        $idPropostaVigente = (new Seguro_Model_Propostas())
                ->getPropostasVigentes([$this->getRequest()->getParam('id_proposta')])[0]['id_proposta'];

        $this->view->itensSegurados = (new Sinistro2_Model_LaudoXMLImportacao())
            ->getResumoItens(
                $idPropostaVigente,
                $this->getRequest()->getParam('id_vistoria')
            );
        
        foreach ($this->view->itensSegurados as $key => $item) {
            switch($item['id_status']) {
                case StatusImportacaoLaudoXmlEnum::ENVIADO:
                case StatusImportacaoLaudoXmlEnum::ENVIADO_NAO_ASSINADO:
                case StatusImportacaoLaudoXmlEnum::DISPENSADO:
                        $this->view->itensSegurados[$key]['rowBackgroundColor'] = 'background-color: #D3D3D3';
                        $this->view->itensSegurados[$key]['rowColor'] = '';
                    break;
                case StatusImportacaoLaudoXmlEnum::INCONSISTÊNCIA:
                        $this->view->itensSegurados[$key]['rowBackgroundColor'] = 'background-color: red;';
                        $this->view->itensSegurados[$key]['rowColor'] = '';
                    break;
                case StatusImportacaoLaudoXmlEnum::PENDENTE:
                        $this->view->itensSegurados[$key]['rowBackgroundColor'] = 'background-color: black;';
                        $this->view->itensSegurados[$key]['rowColor'] = 'color: white;';
                    break;
                default:
                        $this->view->itensSegurados[$key]['rowBackgroundColor'] = '';
                        $this->view->itensSegurados[$key]['rowColor'] = '';
                    break;
            }
        }

        $this->view->idProcesso = (new Sinistro2_Model_Processos())->getIdProcessoByProposta(
            $this->getRequest()->getParam('id_proposta')
        );

        $this->view->vistoriadores = (new Sistema_Model_Funcionarios())->getVistoriadores($this->getRequest()->getParam('id_empresa'), true);
        $this->view->idProposta = $this->getRequest()->getParam('id_proposta');
        $this->view->idPropostaMae = (new Seguro_Model_Propostas())->getRow($this->getRequest()->getParam('id_proposta'))->id_proposta_mae;
        $this->view->idEmpresa = $this->getRequest()->getParam('id_empresa');
        $this->view->idVistoria = $this->getRequest()->getParam('id_vistoria');
        $this->view->idAvisos = $this->getRequest()->getParam('id_avisos');
        $this->view->nomeLaudo = $this->getRequest()->getParam('ds_nome_laudo');
        $this->view->idCobertura = $this->getRequest()->getParam('id_cobertura');
        $this->view->idLaudoFinal = $this->getRequest()->getParam('id_laudo_final');
    }

    public function executaxmlAction() {
        $this->isAjax();
        $Adapter = new Zend_File_Transfer_Adapter_Http();
        $Adapter->setDestination(APPLICATION_PATH.'/upload_files/temp/');
        $Adapter->addValidator('Size', false, 2097152);
        $files = $Adapter->getFileInfo();

        try {
            if(!$Adapter->receive($files['file_xml']['name'])) {
                throw new Zend_File_Transfer_Exception('Erro ao receber arquivo XML.');
            }

            if(!$Adapter->receive($files['ds_nome_laudo_fisico']['name'])) {
                throw new Zend_File_Transfer_Exception('Erro ao receber arquivo PDF.');
            }

            $xmlExtension = Agro_Util::getExtension($files['file_xml']['name']);
            $pdfExtension = Agro_Util::getExtension($files['ds_nome_laudo_fisico']['name']);

            if($xmlExtension !== 'xml'){
                throw new MissingExtensionException('Só arquivo do tipo .xml é permitido.');
            }

            if($pdfExtension !== 'pdf'){
                throw new MissingExtensionException('Só arquivo do tipo .pdf é permitido.');
            }

            if (($arquivo = file_get_contents(APPLICATION_PATH.'/upload_files/temp/' . $files['file_xml']['name'])) === FALSE) {
                throw new FileNotFoundException('Não foi possível ler arquivo.');
            }

            //converte o arquivo xml em array
            $dados = json_decode(
                    json_encode(
                        simplexml_load_string(
                            $arquivo
                        ),
                    JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
                ),
                true
            );

            if(!$dados) {
                throw new Exception('Nenhum conteúdo a ser importado.');
            }

            $dados['params'] = $this->getRequest()->getParams();
            $dados['laudo_fisico'] = $Adapter->getFileInfo()['ds_nome_laudo_fisico'];
            $dados['file_xml'] = $Adapter->getFileInfo()['file_xml'];
            $dados['files_already_validated'] = true;

            $xml = new Agro_LaudoXml($dados);
            
            if ($xml->importarLaudo($er)) {
                $result = ['status' => true, 'message' => 'Laudo importado com sucesso'];
            } else {
                throw new Exception($er);
            }

        } catch (Zend_File_Transfer_Exception | MissingExtensionException | Exception $e) {
            $result = [
                'status' => false,
                'message' => $e->getMessage() 
            ];
        }

        $this->getResponse()->setBody(Zend_Json::encode($result));
    }

    public function buscarpropostasindenizacoesagroAction()
    {
        $this->isAjax(true);
        $response['status'] = true;
        
        try {
            $this->view->paginatorPropostas = (new Sinistro2_Model_RelatorioImportacaoIndenizacao())->fetchAllPaginatorProposta(
                false, $this->getRequest()->getParam('pagePropostas'), 60, 'paginator'
            );
        } catch (Exception $e) {
            $this->view->error = $e;
        }
    }
}
