package com.rjconsultores.ventaboletos.service.impl;

import java.net.URL;
import java.rmi.RemoteException;
import java.sql.Connection;
import java.sql.SQLException;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.sql.DataSource;

import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.brazilutils.br.cpfcnpj.CpfCnpj;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.tempuri.IAG;
import org.tempuri.IAGservice;
import org.tempuri.IAGserviceLocator;

import com.rjconsultores.ventaboletos.dao.PuntoVentaDAO;
import com.rjconsultores.ventaboletos.dao.UsuarioUbicacionDAO;
import com.rjconsultores.ventaboletos.entidad.Constante;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.Estacion;
import com.rjconsultores.ventaboletos.entidad.FormaPagoDet;
import com.rjconsultores.ventaboletos.entidad.Parada;
import com.rjconsultores.ventaboletos.entidad.PuntoVenta;
import com.rjconsultores.ventaboletos.entidad.PuntoVentaVO;
import com.rjconsultores.ventaboletos.entidad.Usuario;
import com.rjconsultores.ventaboletos.exception.BusinessException;
import com.rjconsultores.ventaboletos.exception.IntegracionException;
import com.rjconsultores.ventaboletos.exception.ValidacionCampoException;
import com.rjconsultores.ventaboletos.service.ConstanteService;
import com.rjconsultores.ventaboletos.service.EstacionService;
import com.rjconsultores.ventaboletos.service.LogAuditoriaService;
import com.rjconsultores.ventaboletos.service.PuntoVentaService;
import com.rjconsultores.ventaboletos.utilerias.ApplicationProperties;
import com.rjconsultores.ventaboletos.utilerias.CustomEnum;
import com.rjconsultores.ventaboletos.utilerias.UsuarioLogado;
import com.rjconsultores.ws.totvs.service.TotvsService;
import com.rjconsultores.ws.utileria.Atributos;
import com.rjconsultores.ws.utileria.Atributos.CodPaisBanco;
import com.rjconsultores.ws.utileria.Atributos.ContribuinteICMS;
import com.rjconsultores.ws.utileria.Atributos.ContribuinteSimplesNacional;
import com.rjconsultores.ws.utileria.Atributos.InscricaoMunicipal;
import com.rjconsultores.ws.utileria.Atributos.TipoCliente;
import com.rjconsultores.ws.utileria.Atributos.TipoEntidade;
import com.rjconsultores.ws.utileria.Atributos.TipoFornecedor;
import com.rjconsultores.ws.utileria.Atributos.TipoPessoa;
import com.rjconsultores.ws.utileria.RetornoTotvs;
import com.rjconsultores.ws.utileria.RetornoTotvs.TipoRetorno;
import com.rjconsultores.wsag.Constantes;
import com.rjconsultores.wsag.dao.DaoAG;

import AGIntf.TCliente;
import AGIntf.TComissaoServicosCliente;
import AGIntf.TFornecedor;
import AGIntf.TServicosCliente;

/**
 * 
 * @author Administrador
 */
@Service("puntoVentaService")
public class PuntoVentaServiceImpl implements PuntoVentaService {

	private static Logger log = LogManager.getLogger("com.rjconsultores.ws");

	@Autowired
	private PuntoVentaDAO puntoVentaDAO;
	@Autowired
	private ConstanteService constanteService;
	@Autowired
	private EstacionService estacionService;
	@Autowired
	private UsuarioUbicacionDAO usuarioUbicacionDAO;
	@Autowired
	private DataSource dataSource;
	@Autowired
	private LogAuditoriaService logAuditoriaService;

	// FIXME : Remover esse método de quem está usando. Esse método carrega muitos dados
	@Deprecated
	public List<PuntoVenta> obtenerTodos() {
		return puntoVentaDAO.obtenerTodos();
	}

	public PuntoVenta obtenerID(Integer id) {

		PuntoVenta puntoVenta = puntoVentaDAO.obtenerID(id);

		try {
			puntoVenta.clonar();
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return puntoVenta;
	}

	@Transactional(noRollbackFor = { IntegracionException.class, ValidacionCampoException.class})
	public PuntoVenta suscribir(PuntoVenta entidad) throws IntegracionException, ValidacionCampoException {
		entidad.setUsuarioId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
		entidad.setFecmodif(Calendar.getInstance().getTime());
		entidad.setActivo(Boolean.TRUE);

		Exception respEx = null;
		Constante constDesativaTotvs = constanteService.buscarPorNomeConstante("WS_TOTVS_DESATIVA_INTEGRACAO");
		Boolean desativaTotvs = constDesativaTotvs != null && constDesativaTotvs.getValorconstante().equals("1");
		
		// Mantis 15739 - A integração AG deve ser acionada após a persistência dos dados com sucesso.
		// integração AG
		/*
		 * Constante empresasIntegraAG = constanteService.buscarPorNomeConstante("EMPRESAS_INTEGRACAO_AG"); if (entidad.getStatusaprobacion().equals("A") && empresasIntegraAG != null && empresasIntegraAG.getValorconstante() != null && empresasIntegraAG.getValorconstante().contains(entidad.getEmpresa().getEmpresaId().toString())) { log.debug("iniciando integração com AG"); integraAG(entidad); log.debug("fim da integração com AG"); }
		 */
		
		// integração Totvs
		if (!desativaTotvs){
			if (ApplicationProperties.getInstance().isCustomHabilitado(CustomEnum.INTEGRACION_TOTVS.getDescricao())) {
				try {
					
					if (entidad.getIndIntegracion() == null || (entidad.getIndIntegracion().equals(TipoRetorno.PENDENTE.getValor())
							|| entidad.getIndIntegracion().equals(TipoRetorno.ERRO.getValor()))) {
						String resp = integracionTotvs(entidad);
	
						TipoRetorno retornoTotvs = RetornoTotvs.validaRetornoTotvs(resp);
	
						switch (retornoTotvs) {
						case CONCLUIDA:
							entidad.setIndIntegracion(TipoRetorno.CONCLUIDA.getValor());
							break;
	
						case JA_CADASTRADA:
							entidad.setIndIntegracion(TipoRetorno.JA_CADASTRADA.getValor());
							respEx = new IntegracionException(Atributos.MSG_ERRO_JA_CADASTRADO);
							break;
	
						case ERRO:
							entidad.setIndIntegracion(TipoRetorno.ERRO.getValor());
							respEx = new IntegracionException(Atributos.MSG_ERRO_GENERICA + resp);
							break;
	
						default:
							break;
						}
					} else {
						respEx = new IntegracionException(Atributos.MSG_ERRO_NAO_ENVIO);
					}
				} catch (ValidacionCampoException ev) {
					entidad.setIndIntegracion(TipoRetorno.ERRO.getValor());
					respEx = ev;
	
				} catch (Exception e) {
					entidad.setIndIntegracion(TipoRetorno.ERRO.getValor());
					log.error(Atributos.MSG_ERRO_GENERICA, e);
					respEx = new IntegracionException(Atributos.MSG_ERRO_GENERICA + e.getMessage());
				}
				
			}
		}
		if (respEx != null) {
			if (respEx instanceof ValidacionCampoException) {
				throw (ValidacionCampoException) respEx;
			} else if (respEx instanceof IntegracionException) {
				entidad = puntoVentaDAO.suscribir(entidad);
				throw (IntegracionException) respEx;
			}
		}
		entidad = puntoVentaDAO.suscribir(entidad);	
		logAuditoriaService.auditar(null, entidad, entidad.getEmpresa() != null ? entidad.getEmpresa().getEmpresaId() : null);

		
		// Mantis 15739 - A integração AG deve ser acionada após a persistência dos dados com sucesso.
		// integração AG
		Constante empresasIntegraAG = constanteService.buscarPorNomeConstante("EMPRESAS_INTEGRACAO_AG");
		if (entidad.getStatusaprobacion().equals("A") && empresasIntegraAG != null && empresasIntegraAG.getValorconstante() != null && empresasIntegraAG.getValorconstante().contains(entidad.getEmpresa().getEmpresaId().toString())) {
			log.debug("iniciando integração com AG");
			integraAG(entidad);
			log.debug("fim da integração com AG");
		}

		return entidad;
	}
	
	
	private void integraAG(PuntoVenta entidad) throws IntegracionException{
		Connection connection = null;
		try {
			String motivoNaoIntegrado = "";
			
			connection = getConnection();	
			DaoAG.getInstance().setDBConnection(connection);
			
			integrarClienteAG(entidad);	
			if (!entidad.getIndIntegradoAG()){
				motivoNaoIntegrado += "Cliente: " + entidad.getMotivoNaoIntegradoAG();
			}
			integrarFornecedorAG(entidad);			
			if (!entidad.getIndIntegradoAG()){
				motivoNaoIntegrado += "\nFornecedor: " + entidad.getMotivoNaoIntegradoAG();
				
			}
			if (!motivoNaoIntegrado.isEmpty()){
				throw new IntegracionException(motivoNaoIntegrado);
			}
		} finally {
			try {
				if (connection != null && !connection.isClosed()) {
					connection.close();
				}
			} catch (SQLException e) {
				log.error("error fechar conexão", e);
				throw new RuntimeException(e);
			}
		}
	}

	private void integrarFornecedorAG(PuntoVenta entidad) {		
		try {			
			IAGservice service = new IAGserviceLocator();
			IAG iag = DaoAG.getInstance().obterConstante(Constantes.URL_WS_AG) == null ? null : service.getIAGPort(new URL(DaoAG.getInstance().obterConstante(Constantes.URL_WS_AG)));
			TFornecedor fornecedor = null;
			String strFornecedor = "";
			try{
				strFornecedor = iag.getCodigoFornecedorWithIDWS(entidad.getNumPuntoVenta().toString());
				log.debug("Retorno consulta fornecedor ws: " + strFornecedor);
			} catch (RemoteException e) {
				log.error(e.toString());
				entidad.setIndIntegradoAG(false);
				entidad.setMotivoNaoIntegradoAG("Erro ao conectar com o WS: " + e.toString());
				return;
			}
			if (!strFornecedor.contains("ERRO")){
				// retornar msg a informação de registro já cadastrado 
				entidad.setIndIntegradoAG(false);
				entidad.setMotivoNaoIntegradoAG("Fornecedor já cadastrado");
			} else {
				fornecedor = new TFornecedor();
				fornecedor.setNome(entidad.getRazonSocial());
				fornecedor.setNomeFantasia(entidad.getNombpuntoventa());
				fornecedor.setCNPJCPF(entidad.getNumDoCPuntoVenta());
				fornecedor.setGrupo("");
				fornecedor.setReceita("");										
				fornecedor.setCodigo("");
				fornecedor.setCEP(entidad.getCep());
				fornecedor.setLogradouro(""+entidad.getLogradouro());
				fornecedor.setBairro(entidad.getBairro());
				fornecedor.setNumero(""+entidad.getNumero());
				fornecedor.setComplemento(""+entidad.getComplemento());
				fornecedor.setUF(entidad.getUF());
				fornecedor.setCidade(entidad.getCidade());
				fornecedor.setDDD("");
				fornecedor.setFone("");
				fornecedor.setFax("");
				fornecedor.setEmail("");
				fornecedor.setContato("");
				fornecedor.setSite("");
				fornecedor.setRG("");
				fornecedor.setIE("");
				fornecedor.setIM("");
				fornecedor.setReferencia("");
				fornecedor.setFinalidadeTED("");
				fornecedor.setFinalidadeDOC("");
				fornecedor.setCelular("");
				fornecedor.setLeiaute("");
				fornecedor.setBanco("");
				fornecedor.setBancoNumero("");
				fornecedor.setAgencia("");
				fornecedor.setCC("");
				fornecedor.setDVAg("");
				fornecedor.setDVCC("");
				fornecedor.setIDWS(entidad.getNumPuntoVenta());
				try{
					String retornoAG = iag.incluiFornecedor(fornecedor);
					entidad.setIndIntegradoAG(true);
					log.debug(retornoAG);
				} catch (RemoteException e) {
					entidad.setIndIntegradoAG(false);
					entidad.setMotivoNaoIntegradoAG(e.getMessage());
				}
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
	}
	
	private void integrarClienteAG(PuntoVenta entidad) {

		try {

			IAGservice service = new IAGserviceLocator();
			IAG iag = DaoAG.getInstance().obterConstante(Constantes.URL_WS_AG) == null ? null : service.getIAGPort(new URL(DaoAG.getInstance().obterConstante(Constantes.URL_WS_AG)));
			TCliente cli = null;
			String cliStr = "";
			try {
				cliStr = iag.getClienteWithIDWS(entidad.getNumPuntoVenta().toString());
				log.debug("Retorno consulta cliente ws: " + cliStr);
			} catch (RemoteException e) {
				log.error(e.toString());
				entidad.setIndIntegradoAG(false);
				entidad.setMotivoNaoIntegradoAG("Erro ao conectar com o WS: " + e.toString());
				return;
			}
			if (!cliStr.contains("ERRO")) {
				// retornar msg a informação de registro já cadastrado
				entidad.setIndIntegradoAG(false);
				entidad.setMotivoNaoIntegradoAG("Cliente já cadastrado");
			} else {
				cli = new TCliente();
				cli.setCodigo("");
				cli.setNome(entidad.getRazonSocial());
				cli.setNomeFantasia(entidad.getNombpuntoventa());
				cli.setCnpjcpf(entidad.getNumDoCPuntoVenta());
				cli.setGrupo("");
				cli.setAgenteCobrador("");
				cli.setVencimento(0);
				cli.setContaContabil("");
				cli.setCep(entidad.getCep());
				cli.setLogradouro("" + entidad.getLogradouro());
				cli.setBairro(entidad.getBairro());
				cli.setNumero("" + entidad.getNumero());
				cli.setComplemento("" + entidad.getComplemento());
				cli.setUf(entidad.getUF());
				cli.setCidade(entidad.getCidade());
				cli.setDdd("");
				cli.setFone("");
				cli.setDddFax("");
				cli.setFax("");
				cli.setIdentificador("");
				cli.setDddCelular("");
				cli.setCelular("");
				cli.setEmail("");
				cli.setContato("");
				cli.setSite("");
				cli.setRg("");
				cli.setIe("");
				cli.setReceita("");
				cli.setRepresentante("");
				cli.setIM("");
				cli.setCampoExtra1("");
				cli.setCampoExtra10("");
				cli.setCampoExtra2("");
				cli.setCampoExtra3("");
				cli.setCampoExtra4("");
				cli.setCampoExtra5("");
				cli.setCampoExtra6("");
				cli.setCampoExtra7("");
				cli.setCampoExtra8("");
				cli.setCampoExtra9("");
				cli.setCliPagador("");
				cli.setIDWS(entidad.getNumPuntoVenta());
				cli.setServicosCliente(new TServicosCliente());
				cli.getServicosCliente().setServico("");
				cli.getServicosCliente().setEstabelecimento("");
				cli.getServicosCliente().setModalidade("");
				cli.getServicosCliente().setIndexador("");
				cli.getServicosCliente().setAnoMesPrimeiraCobranca("");
				cli.getServicosCliente().setAquisicao(Calendar.getInstance());
				cli.getServicosCliente().setAnoMesReajuste("");
				cli.getServicosCliente().setObservacao("");
				cli.getServicosCliente().setDescricaoNota("");
				cli.getServicosCliente().setComplementoDescricaoNota("");
				cli.getServicosCliente().setContrato("");
				cli.getServicosCliente().setDtCancelamento(Calendar.getInstance());
				cli.getServicosCliente().setObsCancelamento("");
				cli.getServicosCliente().setCRS_Codigo("");
				cli.getServicosCliente().setIDWS(entidad.getNumPuntoVenta());
				
				cli.getServicosCliente().setAcessoSimultaneo(0);
				cli.getServicosCliente().setAgrupaFat(0);
				cli.getServicosCliente().setAnoMesPrimeiraCobranca("");
				cli.getServicosCliente().setAnoMesReajuste("");
				cli.getServicosCliente().setAquisicao(Calendar.getInstance());
				cli.getServicosCliente().setCliente("");
				cli.getServicosCliente().setComissaoServicosCliente(new TComissaoServicosCliente());
				cli.getServicosCliente().setComplementoDescricaoNota("");
				cli.getServicosCliente().setContrato("");
				cli.getServicosCliente().setCRD_Codigo("");
				cli.getServicosCliente().setCRS_Codigo("");
				cli.getServicosCliente().setDescPrevisto(0);
				cli.getServicosCliente().setDescricaoNota("");
				cli.getServicosCliente().setDtCancelamento(Calendar.getInstance());
				cli.getServicosCliente().setEstabelecimento("");
				cli.getServicosCliente().setGrupoDeHoras(0);
				cli.getServicosCliente().setIDWS("");
				cli.getServicosCliente().setIndexador("");
				cli.getServicosCliente().setMCS_Codigo("");
				cli.getServicosCliente().setModalidade("");
				cli.getServicosCliente().setNrLicencas(0);
				cli.getServicosCliente().setObsCancelamento("");
				cli.getServicosCliente().setObservacao("");
				cli.getServicosCliente().setQtdIndexador(0);
				cli.getServicosCliente().setSequencial(0);
				cli.getServicosCliente().setServico("");
				cli.getServicosCliente().setStISS("");
				cli.getServicosCliente().setTamanhoEmpresa(0);
				cli.getServicosCliente().setValorMaximoFortesDoc(0);
				cli.getServicosCliente().setVencimento(0);
				cli.getServicosCliente().setVRP_Codigo("");
				try {
					
//					StringWriter sw = new StringWriter();
//					JAXBContext jaxbContext = JAXBContext.newInstance(TCliente.class);
//					Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
//					jaxbMarshaller.marshal(cli, sw);
//					String xmlString = sw.toString();
//					System.out.println(xmlString);
					
					String retornoAG = iag.incluiCliente(cli);
					entidad.setIndIntegradoAG(true);
					log.debug(retornoAG);
				} catch (RemoteException e) {
					entidad.setIndIntegradoAG(false);
					entidad.setMotivoNaoIntegradoAG(e.getMessage());
				}
			}

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} 
	}
			
	private Connection getConnection() {
		return DataSourceUtils.getConnection(dataSource);
	}
	
	@Transactional(noRollbackFor = { IntegracionException.class, ValidacionCampoException.class})
	public PuntoVenta actualizacion(PuntoVenta entidad) throws IntegracionException, ValidacionCampoException {
		
		PuntoVenta originalClone = null;
		try {
			originalClone = entidad.getCloneObject();
			if(entidad.getTitularId()!=null && originalClone != null) {
				originalClone.setTitularId(entidad.getTitularId().getCloneObject());				
			}
		} catch (Exception e) {
			log.error("Erro ao clonar TitularId",e);
		}
		entidad.setUsuarioId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
		entidad.setFecmodif(Calendar.getInstance().getTime());
		entidad.setActivo(Boolean.TRUE);

		Exception respEx = null;
		Constante constDesativaTotvs = constanteService.buscarPorNomeConstante("WS_TOTVS_DESATIVA_INTEGRACAO");
		Boolean desativaTotvs = constDesativaTotvs != null && constDesativaTotvs.getValorconstante().equals("1");

		// Mantis 15739 - A integração AG deve ser acionada após a persistência dos dados com sucesso.
		// integração AG
		/*
		 * Constante empresasIntegraAG = constanteService.buscarPorNomeConstante("EMPRESAS_INTEGRACAO_AG"); if ( entidad.getStatusaprobacion().equals("A") && empresasIntegraAG != null && empresasIntegraAG.getValorconstante() != null && empresasIntegraAG.getValorconstante().contains(entidad.getEmpresa().getEmpresaId().toString())) { log.debug("iniciando integração com AG"); integraAG(entidad); log.debug("fim da integração com AG"); }
		 */
		
		// integração Totvs
		if (!desativaTotvs){
			if (ApplicationProperties.getInstance().isCustomHabilitado(CustomEnum.INTEGRACION_TOTVS.getDescricao())) {
	
				try {
					if (entidad.getIndIntegracion() == null || (entidad.getIndIntegracion().equals(TipoRetorno.PENDENTE.getValor())
							|| entidad.getIndIntegracion().equals(TipoRetorno.ERRO.getValor()))) {
						String resp = integracionTotvs(entidad);
	
						TipoRetorno retornoTotvs = RetornoTotvs.validaRetornoTotvs(resp);
	
						switch (retornoTotvs) {
						case CONCLUIDA:
							entidad.setIndIntegracion(TipoRetorno.CONCLUIDA.getValor());
							break;
	
						case JA_CADASTRADA:
							entidad.setIndIntegracion(TipoRetorno.JA_CADASTRADA.getValor());
							respEx = new IntegracionException(Atributos.MSG_ERRO_JA_CADASTRADO);
							break;
	
						case ERRO:
							entidad.setIndIntegracion(TipoRetorno.ERRO.getValor());
							respEx = new IntegracionException(Atributos.MSG_ERRO_GENERICA + resp);
							break;
	
						default:
							break;
						}
					} else {
						respEx = new IntegracionException(Atributos.MSG_ERRO_NAO_ENVIO);
					}
				} catch (ValidacionCampoException e) {
					entidad.setIndIntegracion(TipoRetorno.ERRO.getValor());
					respEx = e;
	
				} catch (Exception e) {
					entidad.setIndIntegracion(TipoRetorno.ERRO.getValor());
					log.error(Atributos.MSG_ERRO_GENERICA, e);
					respEx = new IntegracionException(Atributos.MSG_ERRO_GENERICA + e.getMessage());
				}
			}
		}

		entidad = puntoVentaDAO.actualizacion(entidad);	
		logAuditoriaService.auditar(originalClone, entidad, entidad.getEmpresa() != null ? entidad.getEmpresa().getEmpresaId() : null);
		
		if (respEx != null) {
			if (respEx instanceof IntegracionException) {
				throw (IntegracionException) respEx;
			} else if (respEx instanceof ValidacionCampoException) {
				throw (ValidacionCampoException) respEx;
			}
		}

		// Mantis 15739 - A integração AG deve ser acionada após a persistência dos dados com sucesso.
		// integração AG
		Constante empresasIntegraAG = constanteService.buscarPorNomeConstante("EMPRESAS_INTEGRACAO_AG");
		if (entidad.getStatusaprobacion().equals("A") && empresasIntegraAG != null && empresasIntegraAG.getValorconstante() != null && empresasIntegraAG.getValorconstante().contains(entidad.getEmpresa().getEmpresaId().toString())) {
			log.debug("iniciando integração com AG");
			integraAG(entidad);
			log.debug("fim da integração com AG");
		}

		return entidad;
	}

	private boolean tienesEstacionEnPuntoVta(PuntoVenta entidad) {
		List<Estacion> lsEstaciones = estacionService.buscarEstaciones(entidad);
		if (lsEstaciones != null && lsEstaciones.size() > 0) {
			return true;
		}
		return false;
	}

	@Transactional
	public void borrar(PuntoVenta entidad) throws BusinessException {

		if (tienesEstacionEnPuntoVta(entidad)) {
			throw new BusinessException("editarPuntoVentaController.MSG.estacionVinculadaAgenciaOnDelete");
		}

		for (FormaPagoDet forma : entidad.getLsFormaPagoDet()) {
			forma.setUsuarioId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
			forma.setFecmodif(Calendar.getInstance().getTime());
			forma.setActivo(Boolean.FALSE);
		}

		if (entidad.getAgenciaId() != null) {

			entidad.getAgenciaId().setUsuarioId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
			entidad.getAgenciaId().setFecmodif(Calendar.getInstance().getTime());
			entidad.getAgenciaId().setActivo(Boolean.FALSE);

		}

		if (entidad.getComissaoId() != null) {
			entidad.getComissaoId().setUsuarioId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
			entidad.getComissaoId().setFecmodif(Calendar.getInstance().getTime());
			entidad.getComissaoId().setActivo(Boolean.FALSE);
		}

		if (entidad.getDiversosId() != null) {
			entidad.getDiversosId().setUsuarioId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
			entidad.getDiversosId().setFecmodif(Calendar.getInstance().getTime());
			entidad.getDiversosId().setActivo(Boolean.FALSE);
		}

		if (entidad.getTitularId() != null) {
			entidad.getTitularId().setUsuarioId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
			entidad.getTitularId().setFecmodif(Calendar.getInstance().getTime());
			entidad.getTitularId().setActivo(Boolean.FALSE);
		}

		entidad.setUsuarioId(UsuarioLogado.getUsuarioLogado().getUsuarioId());
		entidad.setFecmodif(Calendar.getInstance().getTime());
		entidad.setActivo(Boolean.FALSE);

		puntoVentaDAO.actualizacion(entidad);
		
		logAuditoriaService.auditarExclusao(entidad, entidad.getEmpresa() != null && entidad.getEmpresa() != null ? entidad.getEmpresa().getEmpresaId() : null);

	}

	public List<PuntoVenta> buscaLike(String strEstacion, boolean sinTodos) {
		return puntoVentaDAO.buscaLike(strEstacion, sinTodos);
	}

	public List<PuntoVenta> buscar(String nomPuntoVenta, String numPuntoVenta) {
		return puntoVentaDAO.busca(nomPuntoVenta, numPuntoVenta);
	}

	public List<PuntoVenta> buscaPuntoVenta(String numPuntoVenta) {
		return puntoVentaDAO.buscaPuntoVenta(numPuntoVenta);
	}

	public List<PuntoVenta> buscaPuntoVentaParada(Parada paradaId) {
		return puntoVentaDAO.buscaPuntoVentaParada(paradaId);
	}

	public List<PuntoVenta> buscarPuntoVentaSubordinados(PuntoVenta puntoVenta) {
		List<PuntoVenta> lsPuntoVentaSubordinados = puntoVentaDAO.buscarPuntoVentaSubordinados(puntoVenta);

		return lsPuntoVentaSubordinados;
	}

	public List<PuntoVenta> buscarPuntosVentaMovimentacionBilhetes(List<Empresa> empresas) {
		List<PuntoVenta> puntosVenta = puntoVentaDAO.buscarPuntosVentaMovimentacionBilhetes(empresas);
		return puntosVenta;
	}

	public List<PuntoVenta> buscarPuntosVentaPorUsuario(Usuario usuario) {
		List<PuntoVenta> puntosVenta = usuarioUbicacionDAO.buscarPuntoVentaPorUsuario(usuario);
		return puntosVenta;
	}

	private void validaCampos(PuntoVenta puntoVenta) throws ValidacionCampoException {

		if (puntoVenta.getNumDoCPuntoVenta() == null) {
			throw new ValidacionCampoException("editarPuntoVentaController.erro.numDoCPuntoVenta");
		}

		String cpfOrCnpj = puntoVenta.getNumDoCPuntoVenta().replaceAll("[^0-9.]", "");

		if (!CpfCnpj.isValid(cpfOrCnpj)) {
			throw new ValidacionCampoException("editarPuntoVentaController.erro.cpfCnpj");
		}

		if (puntoVenta.getNumIEPuntoVenta() == null) {
			throw new ValidacionCampoException("editarPuntoVentaController.erro.numIEPuntoVenta");
		}

		if (puntoVenta.getColonia() == null) {
			throw new ValidacionCampoException("editarPuntoVentaController.erro.colonia");
		}

		if (puntoVenta.getCodpostal() == null) {
			throw new ValidacionCampoException("editarPuntoVentaController.erro.cep");
		}

		if (puntoVenta.getDireccioncalle() == null) {
			throw new ValidacionCampoException("editarPuntoVentaController.erro.calle");
		}

		if (puntoVenta.getAgenciaId() == null) {
			throw new ValidacionCampoException("editarPuntoVentaController.erro.agenciaId");
		} else {

			if (puntoVenta.getAgenciaId().getNumagencia() == null) {
				throw new ValidacionCampoException("editarPuntoVentaController.erro.numagencia");
			}
			if (puntoVenta.getAgenciaId().getNumconta() == null) {
				throw new ValidacionCampoException("editarPuntoVentaController.erro.numconta");
			}
			if (puntoVenta.getAgenciaId().getDigito() == null) {
				throw new ValidacionCampoException("editarPuntoVentaController.erro.digito");
			}

			if (puntoVenta.getAgenciaId().getInstiFinanceiraId() == null) {
				throw new ValidacionCampoException("editarPuntoVentaController.erro.instiFinanceiraId");
			} else {
				if (puntoVenta.getAgenciaId().getInstiFinanceiraId().getCodigo() == null) {
					throw new ValidacionCampoException("editarPuntoVentaController.erro.instiFinanceiraId.codigo");
				}
			}
		}
	}

	private String integracionTotvs(PuntoVenta puntoVenta) throws Exception {
		if (ApplicationProperties.getInstance().isCustomHabilitado(CustomEnum.INTEGRACION_TOTVS.getDescricao())) {

			validaCampos(puntoVenta);

			String endpointFornecedor = getEndpointFornecedor();
			String endpointCliente = getEndpointCliente();

			String xidsvp = puntoVenta.getNumPuntoVenta();

			String cnpjEmpresaProtheus = Atributos.CNPJ_EMPRESA_PROTHEUS;

			String nome = puntoVenta.getNombpuntoventa();
			nome = removerAcentosCaracteresEspeciaisTotvs(nome);

			String cgc = puntoVenta.getNumDoCPuntoVenta();

			String endereco = puntoVenta.getDireccioncalle() + "," + ((puntoVenta.getDireccionnumero() == null) ? "" : puntoVenta.getDireccionnumero());
			endereco = removerAcentosCaracteresEspeciaisTotvs(endereco);

			String complemen = puntoVenta.getCompl() == null ? "" : puntoVenta.getCompl();
			complemen = removerAcentosCaracteresEspeciaisTotvs(complemen);

			String bairro = puntoVenta.getColonia() == null ? null : puntoVenta.getColonia().getDesccolonia();
			bairro = removerAcentosCaracteresEspeciaisTotvs(bairro);

			String codmun = puntoVenta.getColonia() == null ? null : puntoVenta.getColonia().getCiudad().getCodmunicipio().toString();
			codmun = (codmun == null) ? "" : StringUtils.leftPad(codmun, 5, '0');

			String est = puntoVenta.getColonia() == null ? null : puntoVenta.getColonia().getCiudad().getEstado().getCveestado();
			String codpais = CodPaisBanco.BRASIL.getValor();

			String cep = puntoVenta.getCodpostal() != null ? puntoVenta.getCodpostal().toString() : null;

			String tel = puntoVenta.getNumtelefonouno();
			String ddd = null;
			try {
				String[] telefone = tel == null ? null : tel.split("\\)");
				ddd = tel == null ? null : telefone[0].replaceAll("\\(", "");
				tel = tel == null ? null : telefone[1].replaceAll("\\(", "");
			} catch (Exception e) {
				tel = puntoVenta.getNumtelefonouno();
			}

			String email = puntoVenta.getDescCorreo() == null ? "" : puntoVenta.getDescCorreo();
			email = removerCaracteresInvalidosXml(email);

			String fax = puntoVenta.getNumfax() == null ? "" : puntoVenta.getNumfax();
			String inscr = puntoVenta.getNumIEPuntoVenta();
			String inscrm = InscricaoMunicipal.ISENTO.name();

			String nreduz = puntoVenta.getRazonSocial() != null ? puntoVenta.getRazonSocial() : puntoVenta.getNombpuntoventa();
			nreduz = removerAcentosCaracteresEspeciaisTotvs(nreduz);

			String simpnac = ContribuinteSimplesNacional.NAO.getValor();

			String tppessoa = TipoFornecedor.OS.name();
			String tppessoaCliente = TipoCliente.F.name();

			String tipoPessoa = TipoPessoa.F.name();

			if (isCNPJ(cgc)) {
				tipoPessoa = TipoPessoa.J.name();
			}

			String obs = StringUtils.isBlank(puntoVenta.getComentarios()) ? "sem obs." : puntoVenta.getComentarios();

			String contaFornecedor = Atributos.CONTA_FORNECEDOR_PROTHEUS;
			String contaCliente = Atributos.CONTA_CLIENTE_PROTHEUS;

			String naturez = "";
			String cnae = "";
			String fator = "";

			String agencia = puntoVenta.getAgenciaId() == null ? "" : puntoVenta.getAgenciaId().getNumagencia();
			String dgverag = "";
			try {
				String[] agenciaComp = agencia == null ? null : agencia.split("-");
				agencia = agencia == null ? null : agenciaComp[0];
				dgverag = agencia == null ? null : agenciaComp[1];
			} catch (Exception e) {
				agencia = puntoVenta.getAgenciaId() == null ? "" : puntoVenta.getAgenciaId().getNumagencia();
			}

			String banco = puntoVenta.getAgenciaId().getInstiFinanceiraId() == null ? "" : puntoVenta.getAgenciaId().getInstiFinanceiraId().getCodigo();
			String ctacorr = puntoVenta.getAgenciaId() == null ? "" : puntoVenta.getAgenciaId().getNumconta();
			String dgverct = puntoVenta.getAgenciaId() == null ? "" : puntoVenta.getAgenciaId().getDigito();

			String resp = null;
			Exception respEx = null;

			try {
				resp = TotvsService.cadastrarFornecedor(endpointFornecedor, bairro, cep, cgc, cnae, codmun, codpais, complemen, contaFornecedor, ddd, email, endereco,
						est, inscr, inscrm, naturez, nreduz, nome, simpnac, tel, tipoPessoa, tppessoa, cnpjEmpresaProtheus, xidsvp, agencia, banco,
						dgverag, ctacorr, dgverct);
			} catch (Exception e) {
				log.error("", e);
				respEx = e;
			}

			String contrib = ContribuinteICMS.NAO.getValor();
			String entid = TipoEntidade.TRANSPORTE_PASSAGEIRO.getValor();
			String pais = "";// segundo orientação da TOTVS, passar em branco

			try {
				resp = TotvsService.cadastrarCliente(endpointCliente, bairro, cep, cgc, codmun, codpais, complemen, contaCliente, contrib, ddd, email, cnpjEmpresaProtheus,
						endereco, entid, fator, fax, inscr, inscrm, naturez, nreduz, nome, obs, pais, tppessoaCliente, tel, tipoPessoa, est, xidsvp);
			} catch (Exception e) {
				log.error("", e);
				respEx = e;
			}

			if (respEx != null) {
				throw respEx;
			}

			return resp;
		}
		return null;
	}

	private String getEndpointFornecedor() {
		Constante constante = constanteService.buscarPorNomeConstante("WS_TOTVS_FORNECEDOR_ENDPOINT");
		if (constante == null) {
			return "";
		}
		return constante.getValorconstante();
	}

	private String getEndpointCliente() {
		Constante constante = constanteService.buscarPorNomeConstante("WS_TOTVS_CLIENTE_ENDPOINT");
		if (constante == null) {
			return "";
		}
		return constante.getValorconstante();
	}

	private String somenteNumeros(String s) {
		if (s == null || StringUtils.isBlank(s)) {
			return "";
		}

		s = StringUtils.trim(s);

		return s.replaceAll("[^0-9]", "");
	}

	private boolean isCNPJ(String vlr) {
		vlr = somenteNumeros(vlr);
		return vlr.length() > 11;
	}

	/**
	 * From xml spec valid chars:<br>
	 * #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]<br>
	 * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.<br>
	 * 
	 * link artigo:http://stackoverflow.com/questions/9710185/how-to-deal-with-invalid-characters-in-a-ws-output-when-using-cxf
	 * 
	 * @param text
	 *            The String to clean
	 * @param replacement
	 *            The string to be substituted for each match
	 * @return The resulting String
	 */
	private String removerCaracteresInvalidosXml(String s) {
		if (s == null) {
			return s;
		}

		String re = "[^\\x09\\x0A\\x0D\\x20-\\xD7FF\\xE000-\\xFFFD\\x10000-x10FFFF]";
		return s.replaceAll(re, "");
	}

	private String removerAcentosCaracteresEspeciaisTotvs(String s) {
		if (StringUtils.isBlank(s)) {
			return s;
		}
		s = StringUtils.trim(s);
		s = removerCaracteresInvalidosXml(s);
		return Normalizer.normalize(s, Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "").replaceAll("\\W", " ");
	}

	@Override
	public List<PuntoVentaVO> buscaPuntoVentaEmpresaSemECF(Empresa empresa) {
		return puntoVentaDAO.buscaPuntoVentaEmpresaSemECF(empresa);
	}
	
	@Override
	public List<PuntoVenta> buscarPuntoVentaPtoVtaComissao(List<Empresa> empresas) {
		List<Integer> empresasId = new ArrayList<Integer>();
		if(empresas != null) {
			for (Empresa empresa : empresas) {
				empresasId.add(empresa.getEmpresaId());
			}
		}
		if(!empresasId.isEmpty()) {
			return puntoVentaDAO.buscarPuntoVentaPtoVtaComissao(empresasId);
		}
		
		return null;
	}
}
