/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.rjconsultores.ventaboletos.dao.hibernate;

import java.util.List;

import org.apache.commons.lang.Validate;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.hibernate.type.BigDecimalType;
import org.hibernate.type.DateType;
import org.hibernate.type.IntegerType;
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 org.springframework.transaction.annotation.Transactional;

import com.rjconsultores.ventaboletos.dao.TarifaDAO;
import com.rjconsultores.ventaboletos.entidad.Categoria;
import com.rjconsultores.ventaboletos.entidad.ClaseServicio;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.Marca;
import com.rjconsultores.ventaboletos.entidad.Moneda;
import com.rjconsultores.ventaboletos.entidad.OrgaoConcedente;
import com.rjconsultores.ventaboletos.entidad.Parada;
import com.rjconsultores.ventaboletos.entidad.Ruta;
import com.rjconsultores.ventaboletos.entidad.Tarifa;
import com.rjconsultores.ventaboletos.entidad.TipoPuntoVenta;
import com.rjconsultores.ventaboletos.entidad.Tramo;
import com.rjconsultores.ventaboletos.entidad.Via;
import com.rjconsultores.ventaboletos.entidad.VigenciaTarifa;
import com.rjconsultores.ventaboletos.exception.BusinessException;
import com.rjconsultores.ventaboletos.utilerias.UsuarioLogado;
import com.rjconsultores.ventaboletos.vo.comissao.TarifaVO;

/**
 * 
 * @author rodrigo
 */
@SuppressWarnings("unchecked")
@Repository("tarifaDAO")
public class TarifaHibernateDAO extends GenericHibernateDAO<Tarifa, Integer> implements TarifaDAO {

	private static final Logger log = LogManager.getLogger(TarifaHibernateDAO.class);

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

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

		return c.list();
	}

	public boolean existe(Marca marca, Tramo tramo, Moneda moneda, ClaseServicio claseServicio, VigenciaTarifa vigenciaTarifa, Ruta ruta, OrgaoConcedente orgaoConcedente) {

		Validate.notNull(marca);
		Validate.notNull(tramo);
		Validate.notNull(moneda);
		Validate.notNull(claseServicio);
		Validate.notNull(vigenciaTarifa);
		Validate.notNull(ruta);
		Validate.notNull(orgaoConcedente);

		Criteria c = getSession().createCriteria(getPersistentClass());

		c.add(Restrictions.eq("marca", marca));
		c.add(Restrictions.eq("tramo", tramo));
		c.add(Restrictions.eq("moneda", moneda));
		c.add(Restrictions.eq("claseServicio", claseServicio));
		c.add(Restrictions.eq("vigenciaTarifa", vigenciaTarifa));
		c.add(Restrictions.eq("ruta", ruta));
		c.add(Restrictions.eq("orgaoConcedente", orgaoConcedente));

		c.setProjection(Projections.rowCount());

		return (HibernateFix.count(c.list()) > 0);
	}

	public List<Tarifa> pesquisar(Marca marca, Parada origem, Parada destino, Moneda moneda, ClaseServicio claseServicio, VigenciaTarifa vigenciaTarifa, Categoria categoria, TipoPuntoVenta tipoPuntoVenta) {

		Criteria c = getSession().createCriteria(getPersistentClass());
		c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

		Criteria cCategoria = null;
		if (categoria != null) {
			cCategoria = c.createCriteria("lsTarifaCategoria");
			cCategoria.add(Restrictions.eq("categoria", categoria));
			cCategoria.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		}

		Criteria cTipoPuntoVenta = null;
		if (tipoPuntoVenta != null) {
			cTipoPuntoVenta = c.createCriteria("lsTarifaTipoptovta");
			cTipoPuntoVenta.add(Restrictions.eq("tipoPuntoVenta", tipoPuntoVenta));
			cTipoPuntoVenta.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		}

		if (marca != null) {
			c.add(Restrictions.eq("marca", marca));
		}

		Criteria cTramo = c.createCriteria("tramo");
		if (origem != null) {
			cTramo.add(Restrictions.eq("origem", origem));
		}

		if (destino != null) {
			cTramo.add(Restrictions.eq("destino", destino));
		}

		if (moneda != null) {
			c.add(Restrictions.eq("moneda", moneda));
		}

		if (claseServicio != null) {
			c.add(Restrictions.eq("claseServicio", claseServicio));
		}

		if (vigenciaTarifa != null) {
			c.add(Restrictions.eq("vigenciaTarifa", vigenciaTarifa));
		}

		return c.list();
	}

	public Tarifa buscar(Tramo tramo, Marca marca, ClaseServicio claseServicio, VigenciaTarifa vigenciaTarifa, Moneda moneda, Ruta ruta) {

		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq("marca", marca));

		Criteria cTramo = c.createCriteria("tramo");
		cTramo.add(Restrictions.eq(ACTIVO, true));

		c.add(Restrictions.eq("tramo", tramo));
		c.add(Restrictions.eq("claseServicio", claseServicio));
		c.add(Restrictions.eq("vigenciaTarifa", vigenciaTarifa));
		c.add(Restrictions.eq("moneda", moneda));
		c.add(Restrictions.eq("ruta", ruta));
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));

		return (Tarifa) c.uniqueResult();
	}

	public List<Tarifa> buscarTarifasAtivasInativasPorVigencia(VigenciaTarifa vigencia, Empresa empresa) {
		Criteria c = getSession().createCriteria(getPersistentClass());

		if (vigencia != null) {
			c.add(Restrictions.eq("vigenciaTarifa", vigencia));
		}
		if (empresa != null && empresa.getEmpresaId() != -1) {
			c.createCriteria("marca").add(Restrictions.eq("empresa", empresa));
		}

		return c.list();
	}

	public List<Tarifa> buscarTarifasAtivasPorVigencia(VigenciaTarifa vigenciaTarifa) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.add(Restrictions.eq("vigenciaTarifa", vigenciaTarifa));

		return c.list();
	}

	public boolean buscarTarifaExisteTramo(Tramo tramo) {
		Criteria c = this.makeCriteria();
		c.add(Restrictions.eq("tramo", tramo));
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.setProjection(Projections.rowCount());

		return (HibernateFix.count(c.list()) > 0);
	}

	@Override
	@Transactional(rollbackFor = BusinessException.class)
	public void copiarTarifas(VigenciaTarifa vigenciaTarifaOrigem, VigenciaTarifa vigenciaTarifaDestino, Empresa empresa, boolean excluirTarifasDestino) throws BusinessException {
		try {
			StringBuilder sQuery = null;
			if (excluirTarifasDestino) {
				sQuery = new StringBuilder("DELETE FROM TARIFA WHERE VIGENCIATARIFA_ID = :VIGENCIATARIFAID ");
				SQLQuery qrUpdate = getSession().createSQLQuery(sQuery.toString());
				qrUpdate.setParameter("VIGENCIATARIFAID", vigenciaTarifaDestino.getVigenciatarifaId());
				qrUpdate.executeUpdate();
			}

			sQuery = new StringBuilder("INSERT INTO TARIFA( ");
			sQuery.append("TARIFA_ID,PRECIO,PRECIOREDABIERTO,TRAMO_ID,MARCA_ID,CLASESERVICIO_ID,PRECIOORIGINAL,MONEDA_ID,VIGENCIATARIFA_ID,STATUSTARIFA,ACTIVO,FECMODIF,")
					.append("USUARIO_ID,IMPORTETAXAEMBARQUE,IMPORTEPEDAGIO,IMPORTEOUTROS,IMPORTESEGURO,ORGAOCONCEDENTE_ID,RUTA_ID,ORIGEN_ID,DESTINO_ID,IMPORTETPP) ")
					.append("  SELECT "
							+ "TARIFA_SEQ.NEXTVAL, "
							+ "PRECIO, "
							+ "PRECIOREDABIERTO, "
							+ "TRAMO_ID, "
							+ "tarifa.MARCA_ID, "
							+ "CLASESERVICIO_ID, "
							+ "PRECIOORIGINAL, "
							+ "MONEDA_ID, "
							+ ":VIGENCIATARIFAIDDESTINO, "
							+ "STATUSTARIFA, "
							+ "1, "
							+ "sysdate, "
							+ ":USUARIOID, "
							+ "IMPORTETAXAEMBARQUE, "
							+ "IMPORTEPEDAGIO, "
							+ "IMPORTEOUTROS, "
							+ "IMPORTESEGURO, "
							+ "ORGAOCONCEDENTE_ID, "
							+ "RUTA_ID, "
							+ "ORIGEN_ID, "
							+ "DESTINO_ID, "
							+ "IMPORTETPP "

							+ "FROM TARIFA tarifa "
							+ "INNER JOIN MARCA marca ON marca.MARCA_ID = tarifa.MARCA_ID "
							+ "WHERE tarifa.ACTIVO = 1 AND VIGENCIATARIFA_ID = :VIGENCIATARIFAIDORIGEM");

			if (!excluirTarifasDestino) {
				sQuery.append(" AND NOT EXISTS(SELECT"
						+ "  tDestino.TRAMO_ID,"
						+ "  tDestino.MARCA_ID,"
						+ "  tDestino.CLASESERVICIO_ID,"
						+ "  tDestino.MONEDA_ID,"
						+ "  tDestino.ORGAOCONCEDENTE_ID,"
						+ "  tDestino.RUTA_ID"
						+ "  FROM TARIFA tDestino"
						+ "  WHERE"
						+ "  tDestino.TRAMO_ID = tarifa.TRAMO_ID"
						+ "  AND tDestino.MARCA_ID = tarifa.MARCA_ID"
						+ "  AND tDestino.CLASESERVICIO_ID = tarifa.CLASESERVICIO_ID"
						+ "  AND tDestino.MONEDA_ID = tarifa.MONEDA_ID"
						+ "  AND tDestino.ORGAOCONCEDENTE_ID = tarifa.ORGAOCONCEDENTE_ID"
						+ "  AND tDestino.RUTA_ID = tarifa.RUTA_ID"
						+ "  AND tdestino.ACTIVO = 1"
						+ "  AND VIGENCIATARIFA_ID = :VIGENCIATARIFAIDDESTINO)");
			}

			if (empresa != null && empresa.getEmpresaId() != -1) {
				sQuery.append("  AND marca.EMPRESA_ID = :EMPRESA_ID");
			}

			SQLQuery qrInsert = getSession().createSQLQuery(sQuery.toString());
			qrInsert.setParameter("VIGENCIATARIFAIDORIGEM", vigenciaTarifaOrigem.getVigenciatarifaId());
			qrInsert.setParameter("VIGENCIATARIFAIDDESTINO", vigenciaTarifaDestino.getVigenciatarifaId());
			qrInsert.setParameter("USUARIOID", UsuarioLogado.getUsuarioLogado().getUsuarioId());

			if (empresa != null && empresa.getEmpresaId() != -1) {
				qrInsert.setParameter("EMPRESA_ID", empresa.getEmpresaId());
			}
			qrInsert.executeUpdate();

		} catch (Exception e) {
			log.error(e.getMessage());
			throw new BusinessException(e.getMessage(), e.getCause());
		}
	}

	@Override
	public boolean existeTarifas(VigenciaTarifa vigenciaTarifa) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.add(Restrictions.eq("vigenciaTarifa", vigenciaTarifa));
		c.setProjection(Projections.rowCount());
		return (HibernateFix.count(c.list()) > 0);
	}

	@Override
	public void excluirTodasTarifas(Moneda moneda, Marca marca, ClaseServicio claseServicio, VigenciaTarifa vigenciaTarifa, Parada origem,
			Parada destino, Categoria categoria, TipoPuntoVenta tipoPuntoVenta, Ruta ruta, Via via, Boolean vende, Integer usuarioModifId) {
		StringBuilder hql = new StringBuilder();
		try {
		hql.append(" update Tarifa tb set activo = 0, fecmodif = sysdate(), usuarioId = ").append(usuarioModifId).append(" where tarifaId in (");
		hql.append(" select t.tarifaId from Tarifa t ");
		
		if (vende != null) {
			hql.append(" inner join tb.ruta.rutaCombinacionList AS rutaCombinacionList" );
		}

		if (categoria == null && tipoPuntoVenta == null) {
			hql.append(" where 0 = 0 ");
		}

		if (categoria != null) {
			hql.append(" inner join tb.lsTarifaCategoria as tarifascategoria ");
			hql.append(" where 0 = 0 and tarifascategoria.categoria.categoriaId = " + categoria.getCategoriaId());
		}

		if (tipoPuntoVenta != null) {
			hql.append(" inner join tb.lsTarifaTipoptovta as tarifastipoptovta ");
			if (categoria == null) {
				hql.append(" where 0 = 0 and tarifastipoptovta.tipoPuntoVenta.tipoptovtaId = " + tipoPuntoVenta.getTipoptovtaId());
			} else {
				hql.append(" and tarifastipoptovta.tipoPuntoVenta.tipoptovtaId = " + tipoPuntoVenta.getTipoptovtaId());
			}
		}

		if (moneda != null) {
			hql.append(" and tb.moneda.monedaId = " + moneda.getMonedaId());
		}

		if (marca != null) {
			hql.append(" and tb.marca.marcaId = " + marca.getMarcaId());
		}

		if (claseServicio != null) {
			hql.append(" and tb.claseServicio.claseservicioId = " + claseServicio.getClaseservicioId());
		}

		if (vigenciaTarifa != null) {
			hql.append(" and tb.vigenciaTarifa.vigenciatarifaId = " + vigenciaTarifa.getVigenciatarifaId());
		}

		if (origem != null) {
			hql.append(" and tb.origen.paradaId = " + origem.getParadaId());
		}

		if (destino != null) {
			hql.append(" and tb.destino.paradaId = " + destino.getParadaId());
		}

		if (ruta != null) {
			hql.append(" and tb.ruta.rutaId = " + ruta.getRutaId());
		}

		if (via != null) {
			hql.append(" and tb.tramo.via.viaId = " + via.getViaId());
		}
		
		if (vende != null) {
			hql.append(" and rutaCombinacionList.indventa = " + vende);
		}
		
		hql.append(")");

		Query sq = getSession().createQuery(hql.toString());
		sq.executeUpdate();
		}catch (Exception e) {
			String mensagem = "Erro ao excluir Tarifas para origemId:" + ( origem!=null ? origem.getParadaId() : "null") +
					" destinoId:" + (destino !=null ? destino.getParadaId() : "null") +
					" marcaId:" + (marca!=null ? marca.getMarcaId() : "null") +
					" rutaId:" + (ruta !=null ? ruta.getRutaId() : "null");
			log.error(mensagem, e);
		}

	}



	@Override
	public List<TarifaVO> obterTarifaOficialPorFiltroVO(Moneda moneda, Marca marca, List<Marca> lsMarcas, Parada origem, Parada destino, ClaseServicio claseServicio, VigenciaTarifa vigenciaTarifa, Categoria categoria, TipoPuntoVenta tipoPuntoVenta, Ruta ruta, Via via, Boolean vende) {
		
		StringBuilder sql = new StringBuilder(" SELECT ");
		sql.append(" t.tarifa_id tarifaid,");
		sql.append(" t.PRECIO precio,");
		sql.append(" t.PRECIOORIGINAL preciooriginal,");
		sql.append(" t.IMPORTEPEDAGIO importepedagio,");
		sql.append(" t.IMPORTETAXAEMBARQUE importetaxaembarque,");
		sql.append(" t.IMPORTESEGURO importeseguro,");
		sql.append(" t.IMPORTETPP importetpp,");
		sql.append(" t.IMPORTEOUTROS importeoutros,");
		sql.append(" t.STATUSTARIFA statustarifa,");
		sql.append(" origem.DESCPARADA descparadaOrigem,");
		sql.append(" destino.DESCPARADA descparadaDestino,");
		sql.append(" via.NOMBVIA nomeVia,");
		sql.append(" ma.DESCMARCA descMarca,");
		sql.append(" v.FECINICIOVIGENCIA feciniciovigencia,");
		sql.append(" v.FECFINVIGENCIA fecfimvigencia,");
		sql.append(" cl.DESCCLASE descclasse,");
		sql.append(" oc.DESCORGAO descorgao,");
		sql.append(" r.prefixo rutaprefixo,");
		sql.append(" r.numruta numruta");
		sql.append(" FROM TARIFA t");
		sql.append(" LEFT JOIN TRAMO tr on (tr.TRAMO_ID = t.TRAMO_ID)");
		sql.append(" LEFT JOIN VIA via on (VIA.VIA_ID=tr.VIA_ID)");
		sql.append(" LEFT JOIN PARADA origem on (origem.PARADA_ID=tr.ORIGEN_ID)");
		sql.append(" LEFT JOIN PARADA destino on (destino.PARADA_ID=tr.DESTINO_ID)");
		sql.append(" LEFT JOIN MARCA ma on (ma.MARCA_ID = t.MARCA_ID)");
		sql.append(" LEFT JOIN VIGENCIA_TARIFA v on (v.VIGENCIATARIFA_ID = t.VIGENCIATARIFA_ID)");	
		sql.append(" LEFT JOIN ruta r ON ( r.ruta_id = t.ruta_id )");
		sql.append(" LEFT JOIN CLASE_SERVICIO cl ON (cl.CLASESERVICIO_ID=t.CLASESERVICIO_ID)");
		sql.append(" LEFT JOIN ORGAO_CONCEDENTE oc ON (oc.ORGAOCONCEDENTE_ID=t.ORGAOCONCEDENTE_ID)");
		if (categoria != null) {
			sql.append("  LEFT JOIN TARIFA_CATEGORIA tc on (tc.TARIFA_ID = t.TARIFA_ID) ");
		}
		if (tipoPuntoVenta != null) {
			sql.append("LEFT JOIN TARIFA_TIPOPTOVTA tt on (tt.TARIFA_ID = t.TARIFA_ID)");
		}
		
		if(vende!=null){
			sql.append(" LEFT JOIN RUTA_COMBINACION rc on (rc.tramo_id = tr.tramo_id)");
		}
		sql.append(" WHERE ");
		sql.append(" t.activo=1 ");
		if (moneda != null) {
			sql.append(" and t.moneda_id=" + moneda.getMonedaId());
		}
		if (marca != null) {
			sql.append(" and t.marca_id=" + marca.getMarcaId());
		} else {
			String stringMarca =" and t.marca_id in (";
			int contador =0;
			for(Marca m:lsMarcas){
				if(contador==0){
					stringMarca=stringMarca+m.getMarcaId().toString();
				}else{
					stringMarca=stringMarca+","+m.getMarcaId();
				}
				contador++;
				if(lsMarcas.size()==contador){
					stringMarca=stringMarca+")";
				}
			}
			sql.append(stringMarca);

		}
		if(ruta!=null){
		   sql.append(" and t.ruta_id=" + ruta.getRutaId());
		}		
		if (origem != null) {
			sql.append(" and origem.parada_id=" + origem.getParadaId());
		}
		if (destino != null) {
			sql.append(" and destino.parada_id=" + destino.getParadaId());
		}
		if (claseServicio != null) {
			sql.append(" and t.claseservicio_id=" + claseServicio.getClaseservicioId());
		}
		if (vigenciaTarifa != null) {
			sql.append(" and t.vigenciatarifa_id=" + vigenciaTarifa.getVigenciatarifaId());
		}
		if (categoria != null) {
			sql.append(" and tc.categoria_id=" + categoria.getCategoriaId());
		}
		if (vigenciaTarifa != null) {
			sql.append(" and t.vigenciatarifa_id=" + vigenciaTarifa.getVigenciatarifaId());
		}
		if (via != null) {
			sql.append(" and via.via_id=" + via.getViaId());
		}
		if (tipoPuntoVenta != null) {
			sql.append(" and tt.tipoptovta_id=" +tipoPuntoVenta.getTipoptovtaId());
		}
		if(vende!=null){
			int simNao=vende?1:0;
			sql.append(" and rc.tramo_id=t.tramo_id and rc.ruta_id=t.ruta_id and rc.activo=1 and rc.INDVENTA="+simNao);
		}

		Query qr = getSession().createSQLQuery(sql.toString())
				.addScalar("tarifaid", IntegerType.INSTANCE)
				.addScalar("precio", BigDecimalType.INSTANCE)
				.addScalar("preciooriginal", BigDecimalType.INSTANCE)
				.addScalar("importepedagio", BigDecimalType.INSTANCE)
				.addScalar("importetaxaembarque", BigDecimalType.INSTANCE)
				.addScalar("importeseguro", BigDecimalType.INSTANCE)
				.addScalar("importetpp", BigDecimalType.INSTANCE)
				.addScalar("importeoutros", BigDecimalType.INSTANCE)
				.addScalar("statustarifa", StringType.INSTANCE)
				.addScalar("descparadaOrigem", StringType.INSTANCE)
				.addScalar("descparadaDestino", StringType.INSTANCE)
				.addScalar("nomeVia", StringType.INSTANCE)
				.addScalar("descMarca", StringType.INSTANCE)
				.addScalar("feciniciovigencia", DateType.INSTANCE)
				.addScalar("fecfimvigencia", DateType.INSTANCE)
				.addScalar("descclasse", StringType.INSTANCE)
				.addScalar("descorgao", StringType.INSTANCE)
				.addScalar("rutaprefixo", StringType.INSTANCE)
				.addScalar("numruta", StringType.INSTANCE)
				.setResultTransformer(Transformers.aliasToBean(TarifaVO.class));
		qr.setMaxResults(5000);
		return (List<TarifaVO>) qr.list();

	}
	
	public void updateTarifa(Tarifa entity) {
		Session session = getSessionFactory().getCurrentSession(); 
		session.update(entity);
	}
}
