/*
 * 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.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.AliasToBeanResultTransformer;
import org.hibernate.type.BooleanType;
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 com.rjconsultores.ventaboletos.dao.PtovtaTipoEstoqueDAO;
import com.rjconsultores.ventaboletos.dao.PuntoVentaDAO;
import com.rjconsultores.ventaboletos.entidad.Conferencia;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.Parada;
import com.rjconsultores.ventaboletos.entidad.PtovtaTipoEstoque;
import com.rjconsultores.ventaboletos.entidad.PuntoVenta;
import com.rjconsultores.ventaboletos.entidad.PuntoVentaVO;
import com.rjconsultores.ventaboletos.utilerias.DateUtil;
import com.rjconsultores.ventaboletos.vo.busquedapacotes.transformer.DatosPuntoVentaResultTransformer;

/**
 * 
 * @author Administrador
 */
@Repository("puntoVentaDAO")
public class PuntoVentaHibernateDAO extends GenericHibernateDAO<PuntoVenta, Integer>
		implements PuntoVentaDAO {

	public static final int ID_PUNTO_VENTA_TODOS = -1;

	@Autowired
	private PtovtaTipoEstoqueDAO ptovtaTipoEstoqueDAO;

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

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

		c.addOrder(Order.asc("nombpuntoventa"));

		return c.list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<PuntoVenta> buscaLike(String strEstacion, boolean sinTodos) {
		Criteria c = getSession().createCriteria(getPersistentClass());

		Criterion cr1 = Restrictions.like("nombpuntoventa", strEstacion, MatchMode.START);

		Criterion crActivo = Restrictions.eq(ACTIVO, Boolean.TRUE);

		if (sinTodos) {
			Criterion crSinTodos = Restrictions.ne("puntoventaId", ID_PUNTO_VENTA_TODOS);
			c.add(crSinTodos);
		}

		PtovtaTipoEstoque supr = ptovtaTipoEstoqueDAO.buscarTipoSuprimento();
		PtovtaTipoEstoque cont = ptovtaTipoEstoqueDAO.buscarTipoContabilidade();

		Criterion suprCont = Restrictions.in("ptovtaTipoEstoque", new PtovtaTipoEstoque[] { supr, cont });

		Criterion pt2 = Restrictions.or(crActivo, suprCont);

		c.add(Restrictions.and(cr1, pt2));

		return c.list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<PuntoVenta> busca(String nomPuntoVenta, String numPuntoVenta) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));

		c.add(Restrictions.eq("nombpuntoventa", nomPuntoVenta));
		c.add(Restrictions.eq("numPuntoVenta", numPuntoVenta));

		return c.list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<PuntoVenta> buscaPuntoVenta(String numPuntoVenta) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.add(Restrictions.eq("numPuntoVenta", numPuntoVenta));

		return c.list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<PuntoVenta> buscaPuntoVentaEmpresa(Empresa empresa) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.add(Restrictions.eq("empresa", empresa));

		return c.list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<PuntoVenta> buscaPuntoVentaParada(Parada parada) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.add(Restrictions.eq("parada", parada));
		c.addOrder(Order.asc("nombpuntoventa"));

		return c.list();
	}

	@Override
	public List<PuntoVentaVO> buscaPuntoVentaEmpresaSemECF(Empresa empresa) {
		StringBuilder sb = new StringBuilder();
		sb.append(" select ");
		sb.append(" DISTINCT ");
		sb.append(" pvaux.PUNTOVENTA_ID as puntoventaId, ");
		sb.append("  pvaux.NOMBPUNTOVENTA  as nombpuntoventa   ");
		sb.append(" from ");
		sb.append(" PUNTO_VENTA pvaux ");
		sb.append("  join PTOVTA_EMPRESA PTOVTAE ");
		sb.append(" ON (PTOVTAE.PUNTOVENTA_ID = PVAUX.PUNTOVENTA_ID) ");
		sb.append("  where ");
		sb.append("      pvaux.PUNTOVENTA_ID  not in  ( ");
		sb.append("        SELECT ");
		sb.append("             DISTINCT   pv.PUNTOVENTA_ID   ");
		sb.append("         FROM ");
		sb.append("             PUNTO_VENTA pv  ");
		sb.append("         INNER JOIN ");
		sb.append("             ESTACION E   ");
		sb.append("                 ON pv.PUNTOVENTA_ID = E .PUNTOVENTA_ID  ");
		sb.append("         INNER JOIN ");
		sb.append("             ESTACION_IMPRESORA ei   ");
		sb.append("                 ON ei.ESTACION_ID = E .ESTACION_ID  ");
		sb.append("         WHERE ");
		sb.append("             ( (ei.TIPOIMPRESSORA = 1  ");
		sb.append(" 							OR ei.TIPOIMPRESSORA = 2) ) ");
		sb.append("            AND ei.ACTIVO = 1  ");
		sb.append("             AND ei.EMPRESA_ID = :empresa_id ");
		sb.append(" 				/*	ORDER BY PUNTOVENTA_ID*/ ");
		sb.append("     )  ");
		sb.append("     and PTOVTAE.EMPRESA_ID = :empresa_id  ");
		sb.append(" 			and PTOVTAE.ACTIVO = 1 ");
		sb.append(" 			AND pvaux.ACTIVO = 1 ");
		sb.append(" 			AND pvaux.PUNTOVENTA_ID <> -1 ");
		sb.append(" ORDER BY ");
		sb.append("    pvaux.PUNTOVENTA_ID ");
		SQLQuery sql = getSession().createSQLQuery(sb.toString())
				.addScalar("puntoventaId", IntegerType.INSTANCE)
				.addScalar("nombpuntoventa", StringType.INSTANCE);
		sql.setInteger("empresa_id", empresa.getEmpresaId());
		sql.setResultTransformer(new AliasToBeanResultTransformer(PuntoVentaVO.class));
		@SuppressWarnings("unchecked")
		List<PuntoVentaVO> puntosVenta = sql.list();
		return puntosVenta;

	}

	@SuppressWarnings("unchecked")
	@Override
	public List<PuntoVenta> buscarPuntoVentaSubordinados(PuntoVenta puntoVenta) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq(ACTIVO, Boolean.TRUE));
		c.add(Restrictions.eq("puntoVentaPadre", puntoVenta));

		return c.list();
	}

	@Override
	public List<PuntoVenta> buscarPuntosVentaMovimentacionBilhetes(List<Empresa> empresas) {

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

		Criterion crtPtovta = Restrictions.and(Restrictions.eq(ACTIVO, Boolean.TRUE), Restrictions.in("empresa", empresas));

		PtovtaTipoEstoque supr = ptovtaTipoEstoqueDAO.buscarTipoSuprimento();
		PtovtaTipoEstoque cont = ptovtaTipoEstoqueDAO.buscarTipoContabilidade();

		Criterion suprCont = Restrictions.in("ptovtaTipoEstoque", new PtovtaTipoEstoque[] { supr, cont });

		c.add(Restrictions.or(suprCont, crtPtovta));

		c.addOrder(Order.asc("nombpuntoventa"));
		@SuppressWarnings("unchecked")
		List<PuntoVenta> puntosVenta = c.list();

		// List<PuntoVenta> puntosVenta = geraListaDummy();

		return puntosVenta;
	}

	@Override
	public List<PuntoVenta> buscarPuntoVentaPorTipoEstoque(PtovtaTipoEstoque tipoEstoque) {
		Criteria c = getSession().createCriteria(getPersistentClass());
		c.add(Restrictions.eq("ptovtaTipoEstoque", tipoEstoque));

		@SuppressWarnings("unchecked")
		List<PuntoVenta> puntosVenta = c.list();

		return puntosVenta;
	}

	@SuppressWarnings("unused")
	private List<PuntoVenta> geraListaDummy() {

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

		PtovtaTipoEstoque supr = ptovtaTipoEstoqueDAO.buscarTipoSuprimento();
		PtovtaTipoEstoque cont = ptovtaTipoEstoqueDAO.buscarTipoContabilidade();

		Criterion suprCont = Restrictions.in("ptovtaTipoEstoque", new PtovtaTipoEstoque[] { supr, cont });

		Criterion crtPtovta = Restrictions.in("puntoventaId", new Integer[] { 1, 2, 3, 786, 1321, 1722 });

		c.add(Restrictions.or(suprCont, crtPtovta));
		@SuppressWarnings("unchecked")
		List<PuntoVenta> puntosVenta = c.list();

		return puntosVenta;
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<String> quantidadeECFPorPuntoVenta(Conferencia conferencia) {

		StringBuilder sql = new StringBuilder();

		sql.append("SELECT imp.NUMSERIE20 ");
		sql.append("FROM CAJA c ");
		sql.append("INNER JOIN fiscal_impressora imp ON c.serieimpfiscal = imp.numserie ");
		sql.append("LEFT JOIN fiscal_r2 r2 ON r2.numserie20 = imp.numserie20 ");
		sql.append("AND r2.datamov = to_char(c.feccreacion, 'yyyymmdd') ");
		sql.append("LEFT JOIN fiscal_r4 r4 ON c.caja_id = r4.caja_id ");
		sql.append("WHERE c.serieimpfiscal IS NOT NULL ");
		sql.append("  AND c.PUNTOVENTA_ID =:puntoVentaId and c.EMPRESACORRIDA_ID =:empresaId ");
		sql.append("  AND  C.FECHORVENTA BETWEEN cast(:dataInicio AS DATE) and cast(:dataFim AS DATE) ");
		sql.append("GROUP BY imp.NUMSERIE20 ");

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

		q.setInteger("puntoVentaId", conferencia.getPuntoVenta().getPuntoventaId());
		q.setInteger("empresaId", conferencia.getEmpresa().getEmpresaId());
		q.setTimestamp("dataInicio", DateUtil.inicioFecha(conferencia.getDatamovimento()));
		q.setTimestamp("dataFim", DateUtil.fimFecha(conferencia.getDatamovimento()));

		return q.list();
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<PuntoVenta> buscarPuntoVentaPtoVtaComissao(List<Integer> empresas) {
		StringBuilder sQuery = new StringBuilder("SELECT DISTINCT pv.PUNTOVENTA_ID, pv.NOMBPUNTOVENTA, pv.ACTIVO ");
		sQuery.append("FROM PTOVTA_COMISSAO ptovta ")
				.append("JOIN PUNTO_VENTA pv ON pv.puntoventa_id = ptovta.puntoventa_id ")
				.append("JOIN EMPRESA em ON em.empresa_id = ptovta.empresa_id ")
				.append("WHERE ptovta.activo = 1 ")
				.append("AND pv.activo = 1 ")
				.append("AND em.activo = 1 ")
				.append("AND em.empresa_id in (:empresas)");

		Query qr = getSession().createSQLQuery(sQuery.toString())
				.addScalar("PUNTOVENTA_ID", IntegerType.INSTANCE)
				.addScalar("NOMBPUNTOVENTA", StringType.INSTANCE)
				.addScalar("ACTIVO", BooleanType.INSTANCE)
				.setResultTransformer(new DatosPuntoVentaResultTransformer());

		qr.setParameterList("empresas", empresas);

		return qr.list();
	}

	
}
