package com.rjconsultores.ventaboletos.rest.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.springframework.stereotype.Service;

import com.rjconsultores.routing.ReadOnlyConnection;
import com.rjconsultores.ventaboletos.constantes.Constantes;
import com.rjconsultores.ventaboletos.dao.AliasServicoDAO;
import com.rjconsultores.ventaboletos.dao.CategoriaDescuentoDAO;
import com.rjconsultores.ventaboletos.dao.CorridaDAO;
import com.rjconsultores.ventaboletos.dao.ParadaDAO;
import com.rjconsultores.ventaboletos.dao.TarifaMinimaDAO;
import com.rjconsultores.ventaboletos.dao.TramoDAO;
import com.rjconsultores.ventaboletos.dao.hibernate.ConstanteHibernateDAO;
import com.rjconsultores.ventaboletos.entidad.AliasServico;
import com.rjconsultores.ventaboletos.entidad.CategoriaDescuento;
import com.rjconsultores.ventaboletos.entidad.Corrida;
import com.rjconsultores.ventaboletos.rest.bean.ParamsSincronizarTramo;
import com.rjconsultores.ventaboletos.utilerias.DateUtil;
import com.rjconsultores.ventaboletos.vo.corrida.CorridaVO;
import com.rjconsultores.ventaboletos.vo.tramo.TramoTarifaVO;
import com.rjconsultores.ventaboletos.vo.tramo.TramoVO;
import com.rjconsultores.ventaboletos.web.utilerias.spring.AppContext;

@Service("sincronizarTramoService")
public class SincronizarTramoService {

	@ReadOnlyConnection
	public List<TramoTarifaVO> buscarListaTramosPorListCorridas(ParamsSincronizarTramo params) throws Exception  {
		List<TramoTarifaVO> listTramoTarifa = new ArrayList<TramoTarifaVO>();

		for (CorridaVO corridaVO : params.getListCorridas()) {
			listTramoTarifa.add( new TramoTarifaVO( corridaVO.getChaveCorrida(), corridaVO.getRutaId(), buscarListaTramosPorId(corridaVO)) );
		}
		
		return listTramoTarifa;
	}
	
	@ReadOnlyConnection 
	public List<TramoVO> buscarListaTramosPorId(CorridaVO corridaVO) throws Exception  {
		TramoDAO tramoDAO = (TramoDAO)AppContext.getApplicationContext().getBean("tramoDAO");
		ParadaDAO paradaDAO = (ParadaDAO)AppContext.getApplicationContext().getBean("paradaDAO");
		CorridaDAO corridaDAO = (CorridaDAO)AppContext.getApplicationContext().getBean("corridaDAO");
		TarifaMinimaDAO tarifaMinimaDAO = (TarifaMinimaDAO)AppContext.getApplicationContext().getBean("tarifaMinimaDAO");
		AliasServicoDAO aliasServicoDAO = (AliasServicoDAO)AppContext.getApplicationContext().getBean("aliasServicoDAO");
		CategoriaDescuentoDAO categoriaDescuentoDAO = (CategoriaDescuentoDAO)AppContext.getApplicationContext().getBean("categoriaDescuentoDAO");
		ConstanteHibernateDAO constanteDAO = (ConstanteHibernateDAO)AppContext.getApplicationContext().getBean("constanteDAO");
		
		final Integer corridaId = Integer.valueOf( corridaVO.getChaveCorrida().split(";")[0] );
		final Date fecCorrida = DateUtil.getDateFromString(corridaVO.getChaveCorrida().split(";")[1], "ddMMyyyy");
		
		CorridaVO corrida = corridaDAO.buscarVOPorId( new Corrida.Id(corridaId, fecCorrida) );
		
		List<TramoVO> listaTramoVO = tramoDAO.buscarListaPorIds(corridaVO.getListTramos(), corridaVO.getChaveCorrida(), corrida.isTarifaEmbarcada() );
		
		boolean isTarifaMinimaHabilitado = Boolean.parseBoolean(constanteDAO.buscarPorNomeConstante("isTarifaMinimaHabilitado").getValorconstante());
		boolean aplicaTarifaMinima = categoriaDescuentoDAO.isAplicaTarifaMinima(Constantes.CATEGORIA_NORMAL, corrida.getEmpresaId());
		
		List<AliasServico> aliasLs = aliasServicoDAO.buscarPorRuta( corridaVO.getRutaId() );
		
		Integer praca = null;
		
		for (TramoVO vo : listaTramoVO) {
			//caso valide que algum cliente use mais de uma praça no cadastro, passar a buscar praça a cada tramo
			if( praca == null ) {
				praca = paradaDAO.buscarPorId(vo.getOrigemId()).getCiudad().getPlaza().getPlazaId();
			}
			
			if(isTarifaMinimaHabilitado && aplicaTarifaMinima ) {
				BigDecimal tarifaMinima = tarifaMinimaDAO.obtenerTarifaMinima(
						corrida.getClaseServicioId(), 
						corrida.getMarcaId(), 
						vo.getOrigemId(), 
						vo.getDestinoId(), 
						praca, 
						vo.getMonedaId(), 
						corrida.getRutaId(), 
						Constantes.CATEGORIA_NORMAL);
				
				if( tarifaMinima !=null && tarifaMinima.compareTo(vo.getValorTarifa()) > 0) {
					vo.setValorTarifa(tarifaMinima);
				}	
			}
			
			if( aliasLs != null && !aliasLs.isEmpty() ) {
				final Integer origemId =  vo.getOrigemId();
				final Integer destinoId = vo.getDestinoId();
				
				AliasServico aC = null;
				try {
					aC = (AliasServico) CollectionUtils.find(aliasLs, new Predicate() {
						
						@Override
						public boolean evaluate(Object arg0) {
							AliasServico alias = (AliasServico)arg0;
							
							return alias.getCorridaId() != null && alias.getCorridaId().equals( corridaId )
									&& alias.getOrigen().getParadaId().equals(origemId)
									&& alias.getDestino().getParadaId().equals(destinoId);
						}
					});
					
					if(aC == null) {
						aC = (AliasServico) CollectionUtils.find(aliasLs, new Predicate() {
							
							@Override
							public boolean evaluate(Object arg0) {
								AliasServico alias = (AliasServico)arg0;
								
								return alias.getOrigen().getParadaId().equals(origemId)
										&& alias.getDestino().getParadaId().equals(destinoId)
										&& alias.getCorridaId() == null;
							}
						});
					}
				}catch(Throwable th) {
					throw new Exception("erro ao carrgar o alias",th);
				}
				
				if (aC != null) {
					vo.setAliasdestinoId(aC.getAliasDestino().getParadaId());
					vo.setAliasorigenId(aC.getAliasOrigen().getParadaId());
					vo.setDescAliasdestino(aC.getAliasDestino().getDescparada());
					vo.setDescAliasorigen(aC.getAliasOrigen().getDescparada());
				}
			}
		}
		
		return listaTramoVO;
	}
	
}
