package com.rjconsultores.ventaboletos.dao.hibernate;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.hibernate.SQLQuery;
import org.hibernate.SessionFactory;
import org.hibernate.type.BigDecimalType;
import org.hibernate.type.DateType;
import org.hibernate.type.IntegerType;
import org.hibernate.type.StringType;
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 com.rjconsultores.ventaboletos.dao.IntegracaoDerPrDAO;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.utilerias.DateUtil;
import com.rjconsultores.ventaboletos.vo.exportacao.QdmpDerCabecaVo;
import com.rjconsultores.ventaboletos.vo.exportacao.QdmpDerLinhaVo;
import com.rjconsultores.ventaboletos.vo.exportacao.QdmpDerRodapeVo;

@Repository("integracaoDerPrDAO")
@SuppressWarnings("unchecked")
public class IntegracaoDerPrHibernateDAO extends GenericHibernateDAO<QdmpDerLinhaVo, Integer> implements IntegracaoDerPrDAO {

    @Autowired
    public IntegracaoDerPrHibernateDAO(
            @Qualifier("sessionFactory") SessionFactory factory) {
        setSessionFactory(factory);
    }
    
	@Override
    public List<QdmpDerLinhaVo> buscarDadosImportacaoLinha(Date inicio, Date fim, Empresa empresa, Integer linhaId) {
    	
    	StringBuilder sb = new StringBuilder();
    	sb.append(" SELECT * ");
    	sb.append(" FROM ");
    	sb.append("    ( ");
    	sb.append("        SELECT ");
    	sb.append("            e.codder as codemp,  ");
    	sb.append("            r.prefixo as linha, ");
    	sb.append("            rc.codigoderpr as secao,  ");
    	sb.append("            count( distinct b.boleto_id) AS bilhete, ");
    	sb.append("            ( CASE ");
    	sb.append("                WHEN r.indsentidoida = 0 THEN ");
    	sb.append("            	    'VOLTA' ");
    	sb.append("            	ELSE ");
    	sb.append("            	    'IDA' ");
    	sb.append("            	END ) AS sentido, ");
    	sb.append("            count( distinct CASE ");
    	sb.append("            	WHEN (co.tiposervicio_id = 1 ) THEN ");
    	sb.append("            	    b.boleto_id ");
    	sb.append("            	ELSE ");
    	sb.append("            	    null ");
    	sb.append("            	END ) AS ord, ");
    	sb.append("            count( distinct CASE ");
    	sb.append("            	WHEN ((b.origen_id = co.origen_id and b.destino_id = co.destino_id) and co.tiposervicio_id = 2 ) THEN ");
    	sb.append("            	    b.boleto_id ");
    	sb.append("            	ELSE ");
    	sb.append("            	    null ");
    	sb.append("            	END ) AS rft, ");
    	sb.append("            count( distinct CASE ");
    	sb.append("            	WHEN ((b.origen_id <> co.origen_id or b.destino_id <> co.destino_id) and co.tiposervicio_id = 2 ) THEN ");
    	sb.append("            	    b.boleto_id ");
    	sb.append("            	ELSE ");
    	sb.append("            	    null ");
    	sb.append("            	END ) AS rfp, ");
    	sb.append("            count( distinct CASE ");
		sb.append("            WHEN ((b.origen_id <> co.origen_id or b.destino_id <> co.destino_id) and co.tiposervicio_id = 2 ) THEN ");
		sb.append("                 b.corrida_id ");
        sb.append("            ELSE ");
		sb.append("                 null ");
        sb.append("            END ) AS viagRfp ");
        
        preencheFrom(sb);
    	preencheWhere(linhaId, sb);
    	
    	sb.append("        GROUP BY ");
    	sb.append("            r.prefixo, ");
    	sb.append("            e.codder, ");
    	sb.append("            rc.codigoderpr, ");
    	sb.append("            r.indsentidoida ");
    	sb.append("    ) PIVOT ( ");
    	sb.append("        sum ( bilhete ) tot, sum( ord) ord, sum( rft ) rft, sum(rfp) rfp ");
    	sb.append("        FOR sentido IN ( 'IDA', 'VOLTA' ) ");
    	sb.append("    ) ");
    	sb.append(" ORDER BY ");
    	sb.append("    linha, secao ");
		
		SQLQuery qry = getSession().createSQLQuery(sb.toString())
				.addScalar("codemp", IntegerType.INSTANCE)
				.addScalar("linha", StringType.INSTANCE)
				.addScalar("secao", StringType.INSTANCE)
				.addScalar("'IDA'_TOT", IntegerType.INSTANCE)
				.addScalar("'VOLTA'_TOT", IntegerType.INSTANCE)
				.addScalar("'IDA'_ORD", IntegerType.INSTANCE)
				.addScalar("'VOLTA'_ORD", IntegerType.INSTANCE)
				.addScalar("'IDA'_RFT", IntegerType.INSTANCE)
				.addScalar("'VOLTA'_RFT", IntegerType.INSTANCE)
				.addScalar("'IDA'_RFP", IntegerType.INSTANCE)
				.addScalar("'VOLTA'_RFP", IntegerType.INSTANCE)
				.addScalar("viagRfp", IntegerType.INSTANCE);

		qry.setParameter("EMPRESA_ID", empresa.getEmpresaId(), IntegerType.INSTANCE);
		qry.setParameter("DATA_INICIAL", DateUtil.inicioFecha(inicio), DateType.INSTANCE);
		qry.setParameter("DATA_FINAL", DateUtil.inicioFecha(fim), DateType.INSTANCE);
		
		List<QdmpDerLinhaVo> retorno = new ArrayList<QdmpDerLinhaVo>();
		List<Object[]> dados = qry.list();
		
		for (Object[] object : dados) {
			QdmpDerLinhaVo vo = new QdmpDerLinhaVo(object);
			retorno.add(vo);
		}
		
		return retorno;
    }

	@Override
	public String buscarDadosImportacaoCabeca(Date inicio, Date fim, Empresa empresa, Integer linhaId) {
		StringBuilder sb = new StringBuilder();
		sb.append("  SELECT ");
		sb.append("      e.codder as codemp,  ");
		sb.append("      r.prefixo as linha, ");
		sb.append("      count(distinct CASE ");
		sb.append("          WHEN ((b.origen_id = co.origen_id or b.destino_id = co.destino_id) and co.tiposervicio_id = 1 ) THEN ");
		sb.append("              b.corrida_id+ to_char(b.feccorrida, 'ddMMyyyy') ");
		sb.append("          ELSE ");
		sb.append("              null ");
		sb.append("          END ) AS viagOrd, ");
		sb.append("      sum(distinct CASE ");
		sb.append("          WHEN ((b.origen_id = co.origen_id or b.destino_id = co.destino_id) and co.tiposervicio_id = 1 ) THEN ");
		sb.append("              da.cantasientos ");
		sb.append("          ELSE ");
		sb.append("              null ");
		sb.append("          END ) AS lugOrd, ");
		sb.append("      count(distinct CASE ");
		sb.append("          WHEN ((b.origen_id = co.origen_id and b.destino_id = co.destino_id) and co.tiposervicio_id = 2 ) THEN ");
		sb.append("              b.corrida_id+ to_char(b.feccorrida, 'ddMMyyyy') ");
		sb.append("          ELSE ");
		sb.append("              null ");
		sb.append("          END ) AS viagRft, ");
		sb.append("      sum(distinct CASE ");
		sb.append("          WHEN ((b.origen_id = co.origen_id and b.destino_id = co.destino_id) and co.tiposervicio_id = 2 ) THEN ");
		sb.append("              da.cantasientos ");
		sb.append("          ELSE ");
		sb.append("              null ");
		sb.append("          END ) AS lugRft, ");
		sb.append("      count(distinct CASE ");
		sb.append("          WHEN ((b.origen_id <> co.origen_id or b.destino_id <> co.destino_id) and co.tiposervicio_id = 2 ) THEN ");
		sb.append("              b.corrida_id+ to_char(b.feccorrida, 'ddMMyyyy') ");
		sb.append("          ELSE ");
		sb.append("              null ");
		sb.append("          END ) AS viagRfp, ");
		sb.append("      sum(distinct CASE ");
		sb.append("          WHEN ((b.origen_id <> co.origen_id or b.destino_id <> co.destino_id) and co.tiposervicio_id = 2 ) THEN ");
		sb.append("              da.cantasientos ");
		sb.append("          ELSE ");
		sb.append("              null ");
		sb.append("          END ) AS lugRfp ");
        
        preencheFrom(sb);
    	preencheWhere(linhaId, sb);
    	
    	sb.append("  GROUP BY ");
    	sb.append("      r.prefixo, ");
    	sb.append("      e.codder ");
		
		SQLQuery qry = getSession().createSQLQuery(sb.toString())
				.addScalar("codEmp", IntegerType.INSTANCE)
				.addScalar("linha", StringType.INSTANCE)
				.addScalar("viagOrd", IntegerType.INSTANCE)
				.addScalar("lugOrd", IntegerType.INSTANCE)
				.addScalar("viagRft", IntegerType.INSTANCE)
				.addScalar("lugRft", IntegerType.INSTANCE)
				.addScalar("viagRfp", IntegerType.INSTANCE)
				.addScalar("lugRfp", IntegerType.INSTANCE);

		qry.setParameter("EMPRESA_ID", empresa.getEmpresaId(), IntegerType.INSTANCE);
		qry.setParameter("DATA_INICIAL", new Timestamp(DateUtil.inicioFecha(inicio).getTime()), TimestampType.INSTANCE);
		qry.setParameter("DATA_FINAL", new Timestamp(DateUtil.inicioFecha(fim).getTime()), TimestampType.INSTANCE);
		
		Object[] dados = (Object[])qry.uniqueResult();
		QdmpDerCabecaVo cabeca = new QdmpDerCabecaVo(dados);
		
		return cabeca.toString();
	}

	@Override
	public String buscarDadosImportacaoRodape(Date inicio, Date fim, Empresa empresa, Integer linhaId) {
		StringBuilder sb = new StringBuilder();
		sb.append("  SELECT ");
		sb.append("      e.codder as codemp,  ");
		sb.append("      r.prefixo as linha, ");
		sb.append("      count( distinct b.boleto_id) AS totMov, ");
		sb.append("      sum( b.preciopagado ) AS receita, ");
		sb.append("      sum((b.preciopagado - (b.preciopagado * coalesce(ei.porcredbaseicms / 100,0))) * est.icms) / 100 AS icms, ");
		sb.append("      0 as iasp ");
        
        preencheFrom(sb);
    	preencheWhere(linhaId, sb);
    	
    	sb.append("  GROUP BY ");
    	sb.append("      r.prefixo, ");
    	sb.append("      e.codder ");
		
		SQLQuery qry = getSession().createSQLQuery(sb.toString())
				.addScalar("codEmp", IntegerType.INSTANCE)
				.addScalar("linha", StringType.INSTANCE)
				.addScalar("totMov", IntegerType.INSTANCE)
				.addScalar("receita", BigDecimalType.INSTANCE)
				.addScalar("icms", BigDecimalType.INSTANCE)
				.addScalar("iasp", BigDecimalType.INSTANCE);

		qry.setParameter("EMPRESA_ID", empresa.getEmpresaId(), IntegerType.INSTANCE);
		qry.setParameter("DATA_INICIAL", new Timestamp(DateUtil.inicioFecha(inicio).getTime()), TimestampType.INSTANCE);
		qry.setParameter("DATA_FINAL", new Timestamp(DateUtil.inicioFecha(fim).getTime()), TimestampType.INSTANCE);
		
		Object[] dados = (Object[])qry.uniqueResult();
		QdmpDerRodapeVo rodape = new QdmpDerRodapeVo(dados);
		
		return rodape.toString();
	}
	
	private void preencheFrom(StringBuilder sb) {
		sb.append("        FROM ");
    	sb.append("            boleto b ");
    	sb.append("            INNER JOIN corrida co ");
		sb.append("               ON b.corrida_id = co.corrida_id ");
    	sb.append("               AND b.feccorrida = co.feccorrida ");
    	sb.append("               AND co.activo = 1 ");
    	sb.append("            INNER JOIN ruta r ");
		sb.append("               ON b.ruta_id = r.ruta_id ");
    	sb.append("               AND r.activo = 1 ");
    	sb.append("            INNER JOIN marca m ");
		sb.append("               ON m.marca_id = b.marca_id ");
    	sb.append("               AND m.activo = 1 ");
    	sb.append("            INNER JOIN empresa e ");
		sb.append("               ON m.empresa_id = e.empresa_id ");
    	sb.append("               AND e.activo = 1 ");
    	sb.append("            LEFT JOIN rol_operativo ro ");
		sb.append("               ON ro.roloperativo_id = co.roloperativo_id ");
    	sb.append("            LEFT JOIN diagrama_autobus da ");
		sb.append("               ON ro.diagramaautobus_id = da.diagramaautobus_id ");
    	sb.append("            LEFT JOIN corrida_tramo ct ");
		sb.append("               ON b.corrida_id = ct.corrida_id ");
    	sb.append("               AND b.feccorrida = ct.feccorrida  ");
    	sb.append("               and b.origen_id = ct.origen_id ");
    	sb.append("            LEFT JOIN ruta_combinacion rc ");
		sb.append("               on rc.tramo_id = ct.tramo_id  ");
    	sb.append("               and rc.ruta_id = b.ruta_id ");
    	sb.append("               and rc.activo = 1 ");    	
    	sb.append("            inner join parada po ");
    	sb.append("               on po.parada_id = b.origen_id  ");
    	sb.append("               and po.activo = 1 ");
		sb.append("            inner join ciudad ciu ");
		sb.append("               on ciu.ciudad_id = po.ciudad_id ");
		sb.append("               and ciu.activo = 1 ");
		sb.append("            inner join estado est ");
		sb.append("               on est.estado_id = ciu.estado_id ");
		sb.append("               and est.activo = 1 ");
		sb.append("            inner join empresa_imposto ei ");
		sb.append("               on ei.empresa_id = e.empresa_id ");
		sb.append("               and ei.estado_id = est.estado_id ");
		sb.append("               and ei.activo = 1 ");
	}
	
	private void preencheWhere(Integer linhaId, StringBuilder sb) {
		sb.append("        WHERE b.activo = 1 ");
    	sb.append("          and m.empresa_id  = :EMPRESA_ID ");
    	sb.append("          and b.feccorrida BETWEEN :DATA_INICIAL AND :DATA_FINAL ");
				
		if (linhaId != null) {
			sb.append("          and b.ruta_id = " + linhaId );
		}
				
		sb.append("          and b.MOTIVOCANCELACION_ID is null ");
		sb.append("          and b.INDSTATUSBOLETO = 'V' ");
	}
   
}

