<?php
class_alias('Seguro_Model_PropostaStatusDocumentoDigitalizado', 'StatusDocumento');

class Seguro_Model_PropostaDocumentoDigitalizado extends Agro_Db_Table_Abstract {
	protected $_log = true;
	protected $_schema = 'seguro';
	protected $_name = 'propostas_documento_digitalizado';
	protected $_primary = 'id';

	const FILE_PATH = APPLICATION_PATH . '/upload_files/proposta_documentos_digitalizados';

    /**
     * Inclui novos documentos digitalizados para a proposta
     * @param int $idProposta
     * @return void
     * @throws Zend_File_Transfer_Exception
     */
	public function adicionarDocumentos(int $idProposta)
	{
        $adapter = new Zend_File_Transfer_Adapter_Http();
        $adapter->setDestination(self::FILE_PATH);
        $adapter->addValidator('Extension', false, ['jfif', 'pdf', 'jpg', 'jpeg', 'png']);

        if (!$adapter->isValid()) {
            throw new Exception("Formato de arquivo inválido (formato aceito:  PDF, JPG, JPEG, PNG ou JFIF).");
        }

        $numeroArquivo = 1;
        $files = $adapter->getFileInfo();
        

        foreach ($files as $file) {
            $nomeArquivo = $idProposta . "_" . $numeroArquivo . "_" . time() . "_" . $file['name'];

            if (!copy($file['tmp_name'], self::FILE_PATH . "/" . $nomeArquivo)) {
                throw new Exception("Não foi possível copiar o arquivo {$file['name']} para a pasta.");
            }

            $row = $this->createRow();
            $row->id_proposta = $idProposta;
            $row->ds_nome_arquivo = $nomeArquivo;
            $row->save();

            $numeroArquivo++;
        }

        $propostaStatusDocumento = new StatusDocumento();
        $statusAtual = $propostaStatusDocumento->getStatus($idProposta, true);

        if (
            empty($statusAtual)
            || (!in_array(
                $statusAtual['cd_status'],
                [StatusDocumento::STATUS['DOC_BAIXADO'], StatusDocumento::STATUS['DOC_BAIXADO_CHAMADO']]
            ))
        ) {
            $propostaStatusDocumento->atualizarStatus($idProposta, StatusDocumento::STATUS['DOC_ANEXADO']);
        }
    }

    /**
    * Processa um arquivo ZIP contendo dados a serem importados.
    *
    * Este método realiza a extração dos arquivos contidos no ZIP, valida os nomes de acordo com a regra previamente estipulada (numero_proposta+ '-' +numero_endosso Ex: 123456-0)
    * e caso todas as validações sejam bem-sucedidas, persiste as informações na base e salva uma cópia dos arquivos no sistema
    *
    * @return bool Retorna true se o processo for concluído com sucesso, false caso contrário.
    *
    * @throws \InvalidArgumentException Se o caminho do arquivo for inválido ou o arquivo não for um ZIP.
    * @throws \RuntimeException Se ocorrerem erros durante a extração, validação ou persistência dos dados.
    */
    public function adicionarDocumentosEmLote()
	{
        try{
            $adapter = new Zend_File_Transfer_Adapter_Http();
            $adapter->setDestination(self::FILE_PATH);
            $adapter->addValidator('Extension', false, ['zip']);
            $extensoesValidas = [ 'pdf', 'jpeg', 'jpg', 'png'];
                     
            $zip = new ZipArchive();
            #VALIDA SE O ARQUIVO COMPACTADO É ZIP
            if (!$adapter->isValid()) {
                throw new InvalidArgumentException("Formato de arquivo inválido (formato aceito:  ZIP)");
            }

            $file = $adapter->getFileInfo();
            $file = $file['documentozip'];

            if(!$file){
                throw new InvalidArgumentException("Falha ao acessar arquivo zip.");
            }

            $nomeArquivo = $file['name'];
            $erroArquivos = [];
        
            $destination_folder = self::FILE_PATH.$file['tmp_name'];

            #CRIA UM DIRETORIO TEMPORÁRIO PARA EXTRAIR O CONTEÚDO DO ZIP
            if (!file_exists($destination_folder)) {
                mkdir($destination_folder, 0777, true);
            }
            #COPIA O ZIP PARA O DIRETORIO TEMPORÁRIO RECÉM CRIADO
            if (!copy($file['tmp_name'], $destination_folder ."/".$nomeArquivo)) {
        	    throw new RuntimeException("Não foi possível copiar o arquivo {$file['name']} para a pasta.");
            }
            #TENTA ABRIR O ZIP
            if ($zip->open($destination_folder.'/'.$nomeArquivo) === TRUE) {
                #EXTRAI O CONTEUDO DO ZIP PARA O DIRETORIO TEMPORÁRIO RECÉM CRIADO
                $zip->extractTo($destination_folder);
                $zip->close();

                #ITERA SOB TODOS OS ARQUIVOS EXTRAIDOS DO COMPACTADO
                $files = scandir($destination_folder);
                $contadorArquivosAnalisados = 0;
                foreach ($files as $file) {
                    if ($file === '.' || $file === '..' || pathinfo($file, PATHINFO_EXTENSION) === 'zip') continue;
                    $contadorArquivosAnalisados++;
                    $arquivo = explode('-', $file);
                    #VALIDA SE O NOME DO ARQUIVO ESTÁ FORMATADO CORRETAMENTE
                    if(count($arquivo) > 2){
                        $erroArquivos[$file] = 'Nome de arquivo inválido.';
                        continue;
                    }
                    $idProposta         = (int)$arquivo[0];
                    $nrEndossoArquivo   = (int)$arquivo[1];
                    $proposta           = (new Seguro_Model_Propostas())->find($idProposta)->current();
                    if(!$proposta){
                        $erroArquivos[$file] = 'Proposta não localizada.';
                        continue;
                    }else{
                        $nrEndossoProposta  = (new Seguro_Model_Propostas())->find($idProposta)->current()->nr_endosso();
                    }
               
                    $modelPropostasTipoAssinaturaDocumento = new Seguro_Model_PropostasTipoAssinaturaDocumento();
		            $propostaTipoAssinatura = $modelPropostasTipoAssinaturaDocumento->getByProposta($idProposta);

		            if (empty($propostaTipoAssinatura) || $propostaTipoAssinatura[0]['tipo_assinatura'] != Seguro_Model_PropostasTipoAssinaturaDocumento::MANUAL) {
                        $erroArquivos[$file] = "Tipo de assinatura da proposta inválido.";
                        continue;
		            }

                    $propostaStatusDocumento = new StatusDocumento();
                    $statusAtual = $propostaStatusDocumento->getStatus($idProposta, true);
                    #VALIDAÇÃO COM BASE NO STATUS ATUAL
                    $cdStatus = $statusAtual[0]['cd_status'];
                    $permitidos = [
                    StatusDocumento::STATUS['DOC_PENDENTE_ENVIO'],
                    StatusDocumento::STATUS['DOC_PENDENCIA'],
                    StatusDocumento::STATUS['DOC_ANEXADO']
                    ];

                    if (!in_array($cdStatus, $permitidos)) {
                        $erroArquivos[$file] = 'Status do documento digitalizado inválido.';
                        continue;
                    }

                    #VALIDAÇÃO COM BASE NA EXISTENCIA DE UMA PROPOSTA COM O ID INFORMADO E CORRELAÇÃO DESSA PROPOSTA COM O NR_ENDOSSO RECEBIDO
                    if(empty($proposta) || ($nrEndossoArquivo != $nrEndossoProposta)){
                        $erroArquivos[$file] = 'Número de proposta ou endosso inválido.';
                        continue;
                    }else{
                        $extensao = explode('-',$file);
                        $extensao = explode('.', $extensao[1]); 
                        $extensao = $extensao[1];
                        #VALIDA SE O ARQUIVO DESCOMPACTADO ESTÁ COM A EXTENSÃO CORRETA
                        if (!in_array($extensao, $extensoesValidas)) {
                            $erroArquivos[$file] = "Formato de arquivo inválido (formato aceito:  PDF, JPG, JPEG ou PNG).";
                            continue;
                        }
                        #GERA UM NOME DE ARQUIVO UNICO USANDO TIMESTAMP
                        $nomeArquivo = $idProposta.'-'.$nrEndossoArquivo.'_'.time().'.'.$extensao;
                        #Grava caminho da pasta de docs digitalizados + novo nome do arquivo
                        $novoCaminho = self::FILE_PATH.'/'.$nomeArquivo;
                        #Move arquivo para diretório padrão
                        if(!copy($destination_folder."/".$file, $novoCaminho)){
                            $erroArquivos[$file] = "Não foi possível copiar o arquivo {$file} para a pasta.";
                            continue;
                        }
                  
                        #Grava no banco
                        $row = $this->createRow();
                        $row->id_proposta = $idProposta;
                        $row->ds_nome_arquivo = $nomeArquivo;
                        $row->save();
                    }

                    if (empty($statusAtual) || (!in_array($statusAtual['cd_status'],[StatusDocumento::STATUS['DOC_BAIXADO'], StatusDocumento::STATUS['DOC_BAIXADO_CHAMADO']]))) {
                        $propostaStatusDocumento->atualizarStatus($idProposta, StatusDocumento::STATUS['DOC_ANEXADO']);
                    }
                }
                #Remove o diretorio que foi criado para a extração do zip
                $this->removerDiretorio($destination_folder);
       
                $todosArquivosComErro = false;
                $todosArquivosComErro = (count($erroArquivos) == $contadorArquivosAnalisados) ? true : false;
                return [
                'erros_importacao'=>$erroArquivos, 
                'todos_arquivos_com_erro' => $todosArquivosComErro
                ];
            } else {
                return [
                    'errosImportacao'=>
                    [
                        'Falha ao abrir arquivo zip.'=> ''
                    ],
                    'todos_arquivos_com_erro'=>true
                ];
            }
 
        }catch(Exception $e){
            $result['message'] = $e->getMessage();
			$result['status'] = false;
        }
    }

	/**
	 * Busca os documentos de uma proposta
	 * @param int $idProposta
	 * @return array
	 */
	public function getByProposta($idProposta)
	{
		$select = $this->select()->setIntegrityCheck(false);
		$select->from(array('p' => 'seguro.propostas_documento_digitalizado'), '*');
		$select->join(array('u' => 'sistema.usuarios'), 'p.id_usuario_criacao = u.id', 'ds_nome_usuario');
		$select->where("id_proposta={$idProposta}");

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

    /**
     * Deleta um registro da tabela propostas_documento_digitalizado
     * @param $id
     * @return int|void
     * @throws Zend_Db_Table_Exception
     */
	public function delete($id)
	{
		$row = $this->find($id)->current();
		unlink(realpath(self::FILE_PATH . "/" . $row->ds_nome_arquivo));
		
		parent::delete($id, 'id');
	}

    private function removerDiretorio($caminho)
    {  
        if (!is_dir($caminho)) return false;

        $itens = scandir($caminho);
        foreach ($itens as $item) {
            if ($item === '.' || $item === '..') continue;

            $itemPath = $caminho . DIRECTORY_SEPARATOR . $item;
            if (is_dir($itemPath)) {
                removerDiretorio($itemPath); // Recursão para subpastas
            } else {
                unlink($itemPath); // Remove arquivo
            }
        }
        return rmdir($caminho); // Remove o diretório vazio
    }
}
