package com.rjconsultores.ventaboletos.dao.hibernate;

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

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.AliasToBeanResultTransformer;
import org.hibernate.type.BigDecimalType;
import org.hibernate.type.StringType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;

import com.rjconsultores.ventaboletos.dao.GP_PricingDAO;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.GP_Pricing;
import com.rjconsultores.ventaboletos.entidad.GP_PricingVigencia;
import com.rjconsultores.ventaboletos.vo.pricing.GP_PricingRevisaoValoresVO;

@Repository("gp_pricingDAO")
public class GP_PricingHibernateDAO extends GenericHibernateDAO<GP_Pricing, Integer>
		implements GP_PricingDAO {

	@Autowired
	public GP_PricingHibernateDAO(@Qualifier("sessionFactory") SessionFactory factory) {
		setSessionFactory(factory);
	}

	@Override
	public List<GP_Pricing> obtenerTodos() {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, GP_Pricing.ATIVO));

		return c.list();
	}

	public List<GP_Pricing> buscar(String nombPricing, Empresa empresa,
			Short cantboleto, Integer cantdiasanticipacion,
			BigDecimal descuentoporcentaje, BigDecimal descuentoporcredondo) {

		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, GP_Pricing.ATIVO));

		c.add(Restrictions.eq("nombPricing", nombPricing));
		c.add(Restrictions.eq("empresa", empresa));
		c.add(Restrictions.eq("cantboleto", cantboleto));
		c.add(Restrictions.eq("cantdiasanticipacion", cantdiasanticipacion));
		if (descuentoporcentaje != null) {
			c.add(Restrictions.eq("descuentoporcentaje", descuentoporcentaje));
		}
		if (descuentoporcredondo != null) {
			c.add(Restrictions.eq("descuentoporcredondo", descuentoporcredondo));
		}

		return c.list();
	}

	public List<GP_Pricing> buscarPorNombre(String nombPricing) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, GP_Pricing.ATIVO));

		c.add(Restrictions.eq("nombPricing", nombPricing));

		return c.list();
	}

	@Override
	public List<GP_PricingRevisaoValoresVO> buscarPricingRevisaoValoresVO(List<Integer> classeServicioIds,List<Integer> marcaIds, List<Integer> rutaIds, List<Integer> tramoIds, List<GP_PricingVigencia> lsPricingVigencia) {
		StringBuilder sql = new StringBuilder();
		sql.append("	SELECT distinct  ");
		sql.append(" 	  porigen.descparada \"origem\",                                                               ");
		sql.append("     pdestino.descparada \"destino\",                                                             ");
		sql.append("     cs.descclase \"classeServico\",                                                              ");
		sql.append("     coalesce(t.precio,0) + coalesce(t.importetaxaembarque,0) + coalesce(t.importepedagio,0)  ");
		sql.append("     + coalesce(t.importeseguro,0) + coalesce(t.importeoutros,0) \"precioAtual\",                 ");
		sql.append("     coalesce(t.precio,0) \"tarifaAtual\",                                                        ");
		sql.append("     coalesce(t.importetaxaembarque,0) \"taxaEmbarque\",                                          ");
		sql.append("     coalesce(t.importepedagio,0) \"pedagio\",                                                     ");
		sql.append("     coalesce(t.importeseguro,0) \"seguro\",                                                     ");
		sql.append("     coalesce(t.importeoutros,0) \"outros\"                                                     ");
		sql.append(" FROM tarifa t                                                                                ");
		sql.append(" join tramo tr on tr.tramo_id = t.tramo_id                                                    ");
		sql.append(" join parada pOrigen on porigen.parada_id = tr.origen_id                                      ");
		sql.append(" join parada pDestino on pDestino.parada_id = tr.destino_id                                   ");
		sql.append(" join clase_servicio cs on cs.claseservicio_id = t.claseservicio_id                           ");
		sql.append(" join vigencia_tarifa vt on vt.vigenciatarifa_id = t.vigenciatarifa_id                        ");
		sql.append(" join marca m on m.marca_id = t.marca_id                                                      ");
		sql.append(" join ruta r on t.ruta_id = r.ruta_id                                                         ");
		sql.append(" where                                                                                        ");
		sql.append(" t.activo = 1                                                                                 ");
		sql.append(" and vt.activo = 1                                                                            ");
		sql.append(" and tr.activo = 1                                                                            ");
		if(lsPricingVigencia!= null && !lsPricingVigencia.isEmpty()) {
			sql.append(" and (" );
			for (int i = 1; i <= lsPricingVigencia.size(); i++) {
				sql.append(" (:dataInicioPricing between vt.feciniciovigencia and vt.fecfinvigencia                   ");
				sql.append(" or :dataFimPricing between vt.feciniciovigencia and vt.fecfinvigencia)                       ");
				if(i < lsPricingVigencia.size()) {
					sql.append(" or ");
				}
			}
			sql.append(" )" );
		}
		
		if (classeServicioIds != null && !classeServicioIds.isEmpty()) {
			sql.append(" and cs.claseservicio_id in(:listClasseServicioId)                                            ");
		}
		if(tramoIds != null && !tramoIds.isEmpty()) {
			sql.append(" and tr.tramo_id  in (:listTramoId)                                                           ");
		}
		if (marcaIds != null && !marcaIds.isEmpty()) {
			sql.append(" and m.marca_id in(:listMarcaId)                                                          ");
		}
		if (rutaIds != null && !rutaIds.isEmpty()) {
			sql.append(" and r.ruta_id in(:listRutaId)                                                                ");
		}

		Query query = getSession().createSQLQuery(sql.toString())
				.addScalar("origem",StringType.INSTANCE)
				.addScalar("destino",StringType.INSTANCE)
				.addScalar("classeServico", StringType.INSTANCE)
				.addScalar("precioAtual", BigDecimalType.INSTANCE)
				.addScalar("tarifaAtual", BigDecimalType.INSTANCE)
				.addScalar("taxaEmbarque", BigDecimalType.INSTANCE)
				.addScalar("pedagio", BigDecimalType.INSTANCE)
				.addScalar("seguro", BigDecimalType.INSTANCE)
				.addScalar("outros", BigDecimalType.INSTANCE)
				.setResultTransformer(new AliasToBeanResultTransformer(GP_PricingRevisaoValoresVO.class));
		
		if(lsPricingVigencia!= null && !lsPricingVigencia.isEmpty()) {
			for (GP_PricingVigencia pricingVigencia:lsPricingVigencia) {	
				query.setDate("dataInicioPricing", pricingVigencia.getFecinicioventa());
				query.setDate("dataFimPricing", pricingVigencia.getFecfinventa());
			} 
		}
		
		if (classeServicioIds != null && !classeServicioIds.isEmpty()) {
			query.setParameterList("listClasseServicioId", classeServicioIds);
		}
		if(tramoIds != null && !tramoIds.isEmpty()) {
			query.setParameterList("listTramoId", tramoIds);
		}
		if (marcaIds != null && !marcaIds.isEmpty()) {
			query.setParameterList("listMarcaId", marcaIds);
		}
		if (rutaIds != null && !rutaIds.isEmpty()) {
			query.setParameterList("listRutaId", rutaIds);
		}
		
		query.setFetchSize(1000);
		return query.list();
	}
}
