package com.rjconsultores.ventaboletos.dao.hibernate;

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

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.AliasToBeanResultTransformer;
import org.hibernate.type.ShortType;
import org.hibernate.type.TimestampType;
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.CorridaTramoDAO;
import com.rjconsultores.ventaboletos.entidad.Corrida;
import com.rjconsultores.ventaboletos.entidad.CorridaTramo;
import com.rjconsultores.ventaboletos.entidad.Tramo;
import com.rjconsultores.ventaboletos.utilerias.ActivoUtil;
import com.rjconsultores.ventaboletos.utilerias.DateUtil;

@Repository("corridaTramoDAO")
public class CorridaTramoHibernateDAO extends GenericHibernateDAO<CorridaTramo, Integer> implements CorridaTramoDAO {

    @Autowired
    public CorridaTramoHibernateDAO(@Qualifier("sessionFactory") SessionFactory factory) {
        setSessionFactory(factory);
    }
    
    private static final long serialVersionUID = 1L;
	private static final Logger log = LogManager.getLogger(CorridaTramoHibernateDAO.class);

    @Override
    public List<CorridaTramo> obtenerTramoTarjetaEmitida() {
        Criteria c = getSession().createCriteria(getPersistentClass());
        c.add(Restrictions.isNotNull("fechortarjetaviaje"));
        c.add(Restrictions.isNull("indmanttarjeta"));
        c.add(Restrictions.eq("numsecuencia", (short) 1));

        c.add(Restrictions.eq(ACTIVO, ActivoUtil.ATIVO));

        return c.list();
    }

    public List<CorridaTramo> buscarTarjetaMesmaCorrida(CorridaTramo ct) {
        Criteria c = getSession().createCriteria(getPersistentClass());
        c.add(Restrictions.eq(ACTIVO, ActivoUtil.ATIVO));
        c.add(Restrictions.eq("corrida", ct.getCorrida()));

        return c.list();
    }
    
    public List<CorridaTramo> buscarCorridaTramoPorCorrida(Corrida corrida) {
    	try{
    		 String queryStr = "select ct.Numsecuencia as Numsecuencia, ct.Fechorsalida as Fechorsalida, ct.FechorsalidaH as FechorsalidaH, ct.FechorSalidaOriginal as FechorSalidaOriginal, ct.Fechorllegada as Fechorllegada, ct.FechorllegadaH as FechorllegadaH from Corrida_Tramo ct where ct.activo = :activo and ct.corrida_id = :corridaId and ct.feccorrida = :feccorrida ";
    	        Query query = getSession().createSQLQuery(queryStr).addScalar("numsecuencia", ShortType.INSTANCE)
    	        		.addScalar("fechorsalida", TimestampType.INSTANCE)
    	        		.addScalar("fechorsalidaH", TimestampType.INSTANCE)
    	        		.addScalar("fechorSalidaOriginal", TimestampType.INSTANCE)
    	        		.addScalar("fechorllegada", TimestampType.INSTANCE)
    	        		.addScalar("fechorllegadaH", TimestampType.INSTANCE);
    	        
    	        query.setInteger("activo", ActivoUtil.ATIVO);
    	        query.setInteger("corridaId", corrida.getId().getCorridaId());
    	        query.setDate("feccorrida", corrida.getId().getFeccorrida()); 
    	        
    	        query.setResultTransformer(new AliasToBeanResultTransformer(CorridaTramo.class));
    	        
    	        
    	        return (List<CorridaTramo>)query.list();
    		
    	}catch(HibernateException e){
    		log.error(e.getMessage());
    	}
    	 return null;
    }

    public BigDecimal buscarSumTarjetaMesmaCorrida(CorridaTramo ct) {

        String hql = " select sum(t.kmReal) from CorridaTramo ct, Tramo t "
                + " where ct.tramo.tramoId = t.tramoId and ct.activo = 1 "
                + " and ct.corrida.id.corridaId = :id "
                + " and ct.corrida.id.feccorrida = :data "
                + " group by ct.corrida.id.corridaId,ct.corrida.id.feccorrida ";

        Query sq = getSession().createQuery(hql);
        sq.setParameter("id", ct.getCorrida().getId().getCorridaId());
        sq.setDate("data", ct.getCorrida().getId().getFeccorrida());

        BigDecimal km = (BigDecimal) sq.uniqueResult();

        return km;
    }
    
    public List<Tramo> buscarTramoPorCorridaId(Integer corridaId) {
        Criteria c = getSession().createCriteria(getPersistentClass());
        c.add(Restrictions.eq(ACTIVO, ActivoUtil.ATIVO));
        c.createAlias("corrida", "corrida");
        c.add(Restrictions.eq("corrida.id.corridaId", corridaId));
        c.setProjection(Projections.distinct(Projections.property("tramo")));

        return c.list();
    }
    
    @Override
    @Transactional
    public CorridaTramo buscaCorridaTramoByFecCorridaECorridaIdEdOrigemId(Date fecCorrida, Integer corridaId, boolean isAutorizaServicoIniciado, Integer paradaId) {
		try {
	    	StringBuilder hql = new StringBuilder();
			hql.append(" from CorridaTramo as ct  ");
			hql.append(" where ");
			hql.append(isAutorizaServicoIniciado ? " ct.activo <> 0 " : " ct.activo = 1 ");
			hql.append("       and ct.corrida.id.corridaId = :corrida_id ");
			hql.append("       and ct.corrida.id.feccorrida = :feccorrida ");
			hql.append("       and ct.origem.paradaId = :paradaId ");
			hql.append(" order by ct.numsecuencia");
	
			Query sq = getSession().createQuery(hql.toString());
			sq.setInteger("corrida_id", corridaId);
			sq.setDate("feccorrida", fecCorrida);
			sq.setInteger("corrida_id", corridaId);
			sq.setInteger("paradaId", paradaId);
			return (CorridaTramo) sq.uniqueResult();
		}catch (Exception e) {
			log.error("Erro ao obter CorridaTramo para corridaId:" + corridaId + " fecCorrida:" + DateUtil.getStringDate24Hour(fecCorrida) + " paradaId:" + paradaId , e);
		}
		return null;
	}

	@Override
	public List<CorridaTramo> buscaCorridaTramoByFecCorridaECorridaId(Date fecCorrida, Integer corridaId,
			boolean isAutorizaServicoIniciado) {
			Criteria c = getSession().createCriteria(getPersistentClass());
	        c.add(Restrictions.eq(ACTIVO, ActivoUtil.ATIVO));
	        c.createAlias("corrida", "corrida");
	        c.add(Restrictions.eq("corrida.id.corridaId", corridaId));
	        c.add(Restrictions.eq("corrida.id.feccorrida", fecCorrida));
	        //c.setProjection(Projections.distinct(Projections.property("tramo")));
	        return c.list();

	}
	

	@Override
	@Transactional
	public CorridaTramo suscribir(final CorridaTramo entity) {
		try {
			this.getHibernateTemplate().save(entity);
			getHibernateTemplate().flush();

			return entity;
		} catch (final HibernateException ex) {
			throw convertHibernateAccessException(ex);
		}
		
	}

    
}
