package com.rjconsultores.ventaboletos.dao.hibernate;

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

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
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.DetAbastoBoletoDAO;
import com.rjconsultores.ventaboletos.entidad.AbastoBoleto;
import com.rjconsultores.ventaboletos.entidad.Aidf;
import com.rjconsultores.ventaboletos.entidad.DetAbastoBoleto;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.Estacion;
import com.rjconsultores.ventaboletos.entidad.PuntoVenta;

@Repository("detAbastoBoletoDAO")
public class DetAbastoBoletoHibernateDAO extends GenericHibernateDAO<DetAbastoBoleto, Integer>
		implements DetAbastoBoletoDAO {

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

	@Override
	public Long getSecuencia() {

		StringBuffer sql = new StringBuffer();
		sql.append(" select nummovimiento_seq.nextval from dual ");

		Query query = getSession().createSQLQuery(sql.toString());

		BigDecimal secuencia = (BigDecimal) query.uniqueResult();
		return secuencia.longValue();

	}

	@Override
	public List<DetAbastoBoleto> buscaDetAbastoBoletos(AbastoBoleto abastoBoleto) {

		List<DetAbastoBoleto> detAbastoBoletos = findByCriteria(Restrictions.eq("abastoBoleto", abastoBoleto));
		return detAbastoBoletos;
	}

	@Override
	public List<DetAbastoBoleto> buscaDetAbastoBoletos(Estacion origem, String numfolioinicial, String numfoliofinal, String numseriepreimpresa) {

		StringBuilder queryString = new StringBuilder("from DetAbastoBoleto det where ")
				.append(" det.abastoBoleto.estacion.estacionId = :origem")
				.append(" and det.numseriepreimpresa = :numseriepreimpresa")
				.append(" and (det.numfolioinicial >= :numfolioinicial and det.numfoliofinal <= :numfoliofinal) ")
				.append(" order by det.detabastoboletoId");

		Query query = getSession().createQuery(queryString.toString());
		query.setInteger("origem", origem.getEstacionId());
		query.setString("numseriepreimpresa", numseriepreimpresa);
		query.setString("numfolioinicial", numfolioinicial);
		query.setString("numfoliofinal", numfoliofinal);

		List<DetAbastoBoleto> detAbastoBoletos = query.list();

		return detAbastoBoletos;
	}

	@Transactional
	public void desativaDetAbastos(List<DetAbastoBoleto> detAbastoBoletos) {
		Session session = getSessionFactory().getCurrentSession();

		int count = 0;

		for (DetAbastoBoleto det : detAbastoBoletos) {
			det.setActivo(Boolean.FALSE);
			session.update(det);

			if (++count % 20 == 0) {
				session.flush();
				session.clear();
			}
		}

		session.flush();
		session.clear();

	}

	@Override
	public List<DetAbastoBoleto> buscabDetAbastoBoletoAutomatico(Estacion estacion, String numseriepreimpresa) {

		StringBuilder qs = new StringBuilder();
		qs.append(" from DetAbastoBoleto det ");
		qs.append(" where det.activo = 1 ");
		qs.append(" and det.statusoperacion = 1 ");
		qs.append(" and det.abastoBoleto.estacion.estacionId = :estacion ");
		qs.append(" and det.numseriepreimpresa = :numseriepreimpresa ");

		Query query = getSession().createQuery(qs.toString());
		query.setInteger("estacion", estacion.getEstacionId());
		query.setString("numseriepreimpresa", numseriepreimpresa);

		List<DetAbastoBoleto> detAbastoBoletos = query.list();

		return detAbastoBoletos;
	}
	
	@Override
	public List<Object>  buscabDetAbastoBoletoToVerifyIfAidfCanBeEditable(Aidf aidf){
		StringBuilder qs = new StringBuilder();
		
		qs.append(" select detabastoboleto_id from det_abasto_boleto dat where (numseriepreimpresa like ( ");
		qs.append("   select (case when (  select (coalesce ");
		qs.append("                   ( ");
		qs.append("                     (select trim((select to_char( (select aidf_id from aidf where aidf_id = :aidf_id), '000' )  from dual )) from dual) ,  ");
		qs.append("                       '-_-_' ");
		qs.append("                     )  ");
		qs.append("   ) from dual)  = '-_-_' then '' else concat ((select trim((select to_char( (select aidf_id from aidf where aidf_id = :aidf_id), '000' )  from dual )) from dual) , '%' )  end ) from dual ");
		qs.append("    ");
		qs.append("   ) OR dat.aidf_id = :aidf_id) and dat.activo = 1  ");
		
		Query query = getSession().createSQLQuery(qs.toString());
		query.setLong("aidf_id", aidf.getAidfId());
		
		return query.list();
	}

	@Override
	public DetAbastoBoleto buscarPorAidf(Long aidfId, Integer puntoVenta, String folioInicial, String folioFinal) {

		
		StringBuilder qs = new StringBuilder();
		qs.append(" from DetAbastoBoleto det ");
		qs.append(" where det.activo = 1 ");
		qs.append(" and det.abastoBoleto.puntoventa.puntoventaId = :puntoventaId ");
		qs.append(" and det.aidf.aidfId = :aidfId ");
		qs.append(" and cast(det.numfolioinicial as integer) <= :folioInicial ");
		qs.append(" and cast(det.numfoliofinal as integer) >= :folioFinal ");
		qs.append(" order by detabastoboletoId ");

		Query query = getSession().createQuery(qs.toString());
		query.setInteger("puntoventaId", puntoVenta);
		query.setLong("aidfId", aidfId);
		query.setString("folioInicial", folioInicial);
		query.setString("folioFinal", folioFinal);
		
		query.setFetchSize(1);

		List<DetAbastoBoleto> detAbastoBoletos = query.list();
		
		if( detAbastoBoletos.isEmpty() ) {
			return null;
		}
			
		return detAbastoBoletos.get(0);
	}

	@Override
	public List<Aidf> buscarAidfsPorEmpresaAgencia(Empresa empresa, PuntoVenta origem) {
		StringBuilder qs = new StringBuilder();
		qs.append(" select distinct det.aidf ");
		qs.append(" from DetAbastoBoleto det ");
		qs.append(" where det.activo = 1 ");
		qs.append(" and det.abastoBoleto.puntoventa.puntoventaId = :origem ");
		if( empresa.getEmpresaId() != -1) {
			qs.append(" and det.abastoBoleto.empresa.empresaId = :empresa ");
		}

		Query query = getSession().createQuery(qs.toString());
		query.setInteger("origem", origem.getPuntoventaId());
		
		if( empresa.getEmpresaId() != -1) {
			query.setInteger("empresa", empresa.getEmpresaId());
		}

		List<Aidf> aidfs = query.list();

		return aidfs;
	}

}
