package com.rjconsultores.ventaboletos.service.impl;

import java.util.Date;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codehaus.jettison.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.rjconsultores.ventaboletos.dao.ConstanteDAO;
import com.rjconsultores.ventaboletos.dao.SapDAO;
import com.rjconsultores.ventaboletos.entidad.Constante;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.FechamentoCntcorrente;
import com.rjconsultores.ventaboletos.entidad.PuntoVenta;
import com.rjconsultores.ventaboletos.enums.StatusIntegracaoSap;
import com.rjconsultores.ventaboletos.exception.BusinessRuntimeException;
import com.rjconsultores.ventaboletos.rest.IntegracaoSapRest;
import com.rjconsultores.ventaboletos.service.SapService;
import com.rjconsultores.ventaboletos.utilerias.DateUtil;
import com.rjconsultores.ventaboletos.vo.integracao.FechamentoCntCorrenteVO;

@Service("sapService")
public class SapServiceImpl implements SapService{
	
	private static final String INTEGRACAO_SAP_URL = "INTEGRACAO_SAP_URL";
	private static final String INTEGRACAO_SAP_CREDENCIAL = "INTEGRACAO_SAP_CREDENCIAL";
	private static final Logger log = LogManager.getLogger(SapServiceImpl.class); 
	
	@Autowired
	private SapDAO sapDAO;
	
	@Autowired
	private ConstanteDAO constanteDAO;
	
	@Override
	public List<FechamentoCntcorrente> obtenerTodos() {
		return sapDAO.obtenerTodos();
	}

	@Override
	public FechamentoCntcorrente obtenerID(Long id) {
		return sapDAO.obtenerID(id);
	}

	@Override
	@Transactional
	public FechamentoCntcorrente suscribir(FechamentoCntcorrente entidad) {
		return sapDAO.suscribir(entidad);
	}

	@Override
	@Transactional
	public FechamentoCntcorrente actualizacion(FechamentoCntcorrente entidad) {
		return sapDAO.actualizacion(entidad);
	}

	@Override
	@Transactional
	public void borrar(FechamentoCntcorrente entidad) {
		sapDAO.borrar(entidad);

	}
	
	@Override
	public List<FechamentoCntCorrenteVO> obtenerTodosParaRemessa(Empresa empresa, Date dataDe, Date dataAte, String status) {
		return sapDAO.obtenerTodosParaRemessa(empresa, dataDe, dataAte, status, null);
	}
	
	@Override
	public List<FechamentoCntCorrenteVO> obtenerTodosParaRemessa(Empresa empresa, Date dataDe, Date dataAte, String status, PuntoVenta puntoVenta) {
		return sapDAO.obtenerTodosParaRemessa(empresa, dataDe, dataAte, status, puntoVenta);
	}
	
	@Override
	public int remessa(List<FechamentoCntCorrenteVO> fechamentos, boolean processoManual) throws BusinessRuntimeException, Exception {
		int contador = 0;
		IntegracaoSapRest integracaoSapRest = IntegracaoSapRest.getInstance();
		String credenciais = buscaConstante(INTEGRACAO_SAP_CREDENCIAL);		
		String url = buscaConstante(INTEGRACAO_SAP_URL);

		for (FechamentoCntCorrenteVO fechamentoCntcorrente : fechamentos) {
			if( fechamentoCntcorrente.isEnviar()) {
				log.debug("Enviando fechamento:"+ fechamentoCntcorrente.getFechamentocntcorrenteId());
				JSONObject integrado = integracaoSapRest.enviarIntegracaoSap(fechamentoCntcorrente, url, credenciais);
				
				if(integrado == null) {
					atualizaFechamento(fechamentoCntcorrente.getFechamentocntcorrenteId(), StatusIntegracaoSap.NAO_ENVIADO.ordinal());
					log.error("Erro no envio/retorno da requisicao para integracao SAP do fechamentoID: "+fechamentoCntcorrente.getFechamentocntcorrenteId());
					tratarProcessoManual(processoManual, "Erro no envio/retorno da requisicao para integracao SAP do fechamentoID: %s", fechamentoCntcorrente);
				}else if(integrado.getString("Integration").equals("S")) {							
					atualizaFechamento(fechamentoCntcorrente.getFechamentocntcorrenteId(), StatusIntegracaoSap.INTEGRADO.ordinal());
					contador++;
				}else if(integrado.getString("Integration").equals("E")) {
					atualizaFechamento(fechamentoCntcorrente.getFechamentocntcorrenteId(), StatusIntegracaoSap.RECUSADO.ordinal());
					log.warn("Retorno enviado pelo SAP: \r\n"+integrado.getString("Message"));
					tratarProcessoManual(processoManual, "Fechamento: "+fechamentoCntcorrente.getFechamentocntcorrenteId()+"\r\nRetorno enviado pelo SAP: \r\n"+integrado.getString("Message"), fechamentoCntcorrente);
				}
			}
		}
		
		return contador;
	}

	private void tratarProcessoManual(boolean processoManual, String mensagem, FechamentoCntCorrenteVO fechamentoCntcorrente) {
		if(processoManual) {
			throw new BusinessRuntimeException( String.format(mensagem, fechamentoCntcorrente.getFechamentocntcorrenteId()) );
		}
	}

	private boolean atualizaFechamento(Long fechamentocntcorrenteId, int status) throws Exception {
		return sapDAO.atualizaFechamento( fechamentocntcorrenteId, status);
	}

	private String buscaConstante(String constanteString) {
		Constante constante = constanteDAO.buscarPorNomeConstante(constanteString);
		
		if( constante == null || constante.getValorconstante() == null || constante.getValorconstante().isEmpty() ) {
			throw new BusinessRuntimeException("Constante %s não cadastrada", constanteString);
		}
		
		return constante.getValorconstante();
	}

	@Override
	public void integracaoSapAutomatica() throws Exception {
		List<FechamentoCntCorrenteVO>  listaPendente = obtenerTodosParaRemessa(null, DateUtil.getYesterdayDate(), new Date(), "2");		
		
		while(!listaPendente.isEmpty()) {
			log.info("IntegracaoSap: Registro a enviar:"+listaPendente.size());
			remessa(listaPendente, false);
			listaPendente = obtenerTodosParaRemessa(null, DateUtil.getYesterdayDate(), new Date(), "2");
		}
	}
}
