/**
 * 
 */
package com.rjconsultores.ventaboletos.relatorios.impl;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.DataSource;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.Relatorio;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.RelatorioIndiceIRKBean;
import com.rjconsultores.ventaboletos.web.utilerias.NamedParameterStatement;

import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

/**
 * @author valdevir_rj
 * 
 */
public class RelatorioIndiceIRK extends Relatorio {

	private List<RelatorioIndiceIRKBean> lsDadosRelatorio;
	private static Logger log = LogManager.getLogger(RelatorioIndiceIRK.class);
	

	/**
	 * @param parametros
	 * @param conexao
	 */
	public RelatorioIndiceIRK(final Map<String, Object> parametros, final Connection conexao) throws Exception {
		super(parametros, conexao);

		this.setCustomDataSource(new DataSource(this) {
			@Override
			public void initDados() throws Exception {
				try {
					Integer rutaId =  parametros.get("RUTA_ID") != null ? Integer.valueOf(parametros.get("RUTA_ID").toString()) : null;
					Empresa empresa = parametros.get("EMPRESA") != null ? (Empresa) (parametros.get("EMPRESA")) : null;
					String grupoRutaId = parametros.get("GRUPORUTA_ID") != null ? parametros.get("GRUPORUTA_ID").toString() : null;
					String rutaIds = parametros.get("LINHA_FILTRO") != null ? (parametros.get("LINHA_FILTRO").toString()) : null;
					String corridasIds = parametros.get("SERVICO_FILTRO") != null ? (parametros.get("SERVICO_FILTRO").toString()) : null;

					// Executa query relatório e preenche objeto relatório
					lsDadosRelatorio= preencheAgrupaRelatorioBean(preparaExecutaQuery(parametros, conexao, rutaId, empresa, grupoRutaId, rutaIds, corridasIds), parametros);

					// Ordena pela Desc Linha
					Collections.sort(lsDadosRelatorio, new Comparator<RelatorioIndiceIRKBean>() {
						@Override
						public int compare(RelatorioIndiceIRKBean rel1, RelatorioIndiceIRKBean rel2) {
							return rel1.getDescRuta().compareTo(rel2.getDescRuta());
						}
					});

					parametros.put("RELATORIOLIST", lsDadosRelatorio);
					setLsDadosRelatorio(lsDadosRelatorio);
				} catch (Exception e) {
					log.error("Erro ao executar relatório", e);
				}

			}

			/**
			 * @param parametros
			 * @param conexao
			 * @param rutaId
			 * @param empresa
			 * @param grupoRutaId
			 * @return
			 * @throws SQLException
			 */
			private ResultSet preparaExecutaQuery(final Map<String, Object> parametros, final Connection conexao, Integer rutaId, Empresa empresa, String grupoRutaId,String rutaIds, String corridasIds) throws SQLException {
				String sql = getSql(rutaId, grupoRutaId, rutaIds, corridasIds);
				NamedParameterStatement stmt = new NamedParameterStatement(conexao, sql);
				ResultSet rset = null;
				SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
				if (parametros.get("DATA_INICIO") != null) {
					Date dataInicio = (Date) parametros.get("DATA_INICIO");
					stmt.setString("DATA_INICIO", sdf.format(dataInicio));
				}

				if (parametros.get("DATA_FINAL") != null) {
					Date dataFinal = (Date) parametros.get("DATA_FINAL");
					stmt.setString("DATA_FINAL", sdf.format(dataFinal));
				}
				stmt.setInt("empresaId", empresa.getEmpresaId());
				rset = stmt.executeQuery();
				return rset;
			}

		});
	}

	/**
	 * @param lsDadosRelatorio
	 */
	public void setLsDadosRelatorio(List<RelatorioIndiceIRKBean> lsDadosRelatorio) {
		this.setCollectionDataSource(new JRBeanCollectionDataSource(lsDadosRelatorio));
		this.lsDadosRelatorio = lsDadosRelatorio;
	}

	@Override
	public void processaParametros() throws Exception {
	}

	private String getSql(Integer rutaId, String grupoRutaId, String rutaIds, String corridasIds) {
 		String TODOS = "TODOS";

		StringBuilder sb = new StringBuilder();
		
		sb.append("SELECT sum(extensao) AS extensao,");
		sb.append("       servico,");
		sb.append("       rutaid,");
		sb.append("       descruta,");
		sb.append("       CASE");
		sb.append("           WHEN sentido = 1 THEN 'Ida'");
		sb.append("           WHEN sentido = 0 THEN 'Volta'");
		sb.append("       END AS sentido,");		
		sb.append("       gruporuta,");
		sb.append("       indiceirkminimo,");
		sb.append("       hora,");
		sb.append("       SUM(seguro) AS seguro,");
		sb.append("       SUM(txembarque) AS txembarque,");
		sb.append("       SUM(pedagio) AS pedagio,");
		sb.append("       SUM(passagens) AS passagens,");
		sb.append("       SUM(totalhorario) AS totalhorario,");
		sb.append("       round(((SUM(passagens) + SUM(pedagio) + SUM(txembarque) + SUM(seguro)) / sum(extensao)), 2) AS irk, ");
		sb.append("       sum(receitaminima) AS receitaminima,");
		sb.append("       sum(diferencareceita) AS diferencareceita,");
		sb.append("       prefixo, ");
		sb.append("       passageiros, ");
		sb.append("       CASE ");
		sb.append("           WHEN tipo_servico = 1 THEN 'O' ");
		sb.append("           WHEN tipo_servico = 2 THEN 'E' ");
		sb.append("       END AS tipoServico");
		sb.append(" FROM ");
		sb.append("  (SELECT DISTINCT servico,");
		sb.append("                   rutaid,");
		sb.append("                   descruta,");
		sb.append("                   sentido,");
		sb.append("                   gruporuta,");
		sb.append("                   indiceirkminimo,");
		sb.append("                   hora,");
		sb.append("                   (extensao * qtdCorrida) AS extensao,");
		sb.append("                   SUM(seguro) AS seguro,");
		sb.append("                   SUM(txembarque) AS txembarque,");
		sb.append("                   SUM(pedagio) AS pedagio,");
		sb.append("                   SUM(passagens) AS passagens,");
		sb.append("                   (SUM(passagens) + SUM(pedagio) + SUM(txembarque) + SUM(seguro)) AS totalhorario,");
		sb.append("                   round(((SUM(passagens) + SUM(pedagio) + SUM(txembarque) + SUM(seguro)) / extensao ), 2) AS irk,");
		sb.append("                   indiceirkminimo * extensao * qtdCorrida AS receitaminima,");
		sb.append("                   (SUM(passagens) + SUM(pedagio) + SUM(txembarque) + SUM(seguro)) - (indiceirkminimo * extensao * qtdCorrida) AS diferencareceita,");
		sb.append("                   prefixo, ");
		sb.append("                   count(passageiros) AS passageiros,  ");
		sb.append("                   tipo_servico ");
		sb.append("   FROM ");
		
		sb.append("( WITH corridas AS (                                                                                                                         ");
		sb.append("        SELECT                                                                                                                               ");
		sb.append("	                coi.fechorsalida AS feccorrida,                                                                                             ");
		sb.append("	            	cjj.corrida_id,																												");					
		sb.append(" 				coi.tiposervicio_id 			                                                                                            ");
		sb.append("    FROM                                                                                                                                     ");
		sb.append("             caja cjj                                                                                                                        ");
		sb.append("        INNER JOIN ruta     r ON ( cjj.ruta_id = r.ruta_id )                                                                                 ");
		sb.append("        INNER JOIN corrida  coi ON ( coi.corrida_id = cjj.corrida_id                                                                         ");
		sb.append("                                    AND coi.ruta_id = r.ruta_id                                                                              ");
		sb.append("                                    AND coi.activo = 1                                                                                       ");
		sb.append("                                    AND cjj.feccorrida = coi.feccorrida )                                                                    ");
		sb.append("    WHERE                                                                                                                                    ");
		sb.append("            cjj.activo = 1                                                                                                                   ");
		sb.append("        AND cjj.motivocancelacion_id IS NULL                                                                                                 ");
		sb.append("        AND cjj.indstatusboleto = 'V'                                                                                                        ");
		sb.append("              and cjj.feccorrida BETWEEN TO_DATE(:DATA_INICIO, 'DD/MM/YY hh24:mi:ss') AND TO_DATE(:DATA_FINAL, 'DD/MM/YY hh24:mi:ss') 		");
		sb.append(rutaIds == null ||TODOS.equals(rutaIds) ? "" : "   AND    r.ruta_id IN (   " + rutaIds + "   )     											");
		sb.append(corridasIds == null || TODOS.equals(corridasIds)	 ? "" : "   AND    cjj.corrida_id IN (   " + corridasIds + "   )     						");
		sb.append(grupoRutaId == null || TODOS.equals(grupoRutaId) ? "" : "   AND    R.GRUPORUTA_ID IN (   " + grupoRutaId + "   )    							");
		sb.append("              AND cjj.empresacorrida_id =:empresaId 																							");
		sb.append("    GROUP BY ");
		sb.append("        coi.fechorsalida, ");
		sb.append("        cjj.corrida_id, ");
		sb.append("		   coi.tiposervicio_id ");
		sb.append("), corridas_count AS ( ");
		sb.append("    SELECT ");
		sb.append("        to_char(feccorrida, 'HH24:MI')   AS hora, ");
		sb.append("        corrida_id, ");
		sb.append("        tiposervicio_id, ");
		sb.append("        COUNT(*)                         AS quantidade ");
		sb.append("    FROM ");
		sb.append("        corridas ");
		sb.append("    GROUP BY ");
		sb.append("        to_char(feccorrida, 'HH24:MI'), ");
		sb.append("        corrida_id, ");
		sb.append("		   tiposervicio_id");
		sb.append(") ");
		sb.append("SELECT ");
		sb.append("    cj.caja_id                        AS cajaid, ");
		sb.append("    cj.corrida_id                     AS servico, ");
		sb.append("    r.ruta_id                         AS rutaid, ");
		sb.append("    r.descruta                        AS descruta, ");
		sb.append("    r.indsentidoida                   AS sentido, ");
		sb.append("    nvl(e.indiceirk, 0)               AS indiceirkminimo, ");
		sb.append("    nvl(gr.descgrupo, 'Nao Definido') AS gruporuta, ");
		sb.append("    SUM(tr.cantkmreal)                AS extensao, ");
		sb.append("    cj.importeseguro                  AS seguro, ");
		sb.append("    cj.importetaxaembarque            AS txembarque, ");
		sb.append("    cj.importepedagio                 AS pedagio, ");
		sb.append("    cj.preciopagado                   AS passagens, ");
		sb.append("    r.prefixo                         AS prefixo, ");
		sb.append("    cos.hora, ");
		sb.append("    cos.quantidade                    AS qtdcorrida, ");
		sb.append("    COUNT(distinct cj.transacao_id)   AS passageiros, ");
		sb.append("    co.tiposervicio_id                AS tipo_servico ");
		sb.append("FROM ");
		sb.append("    caja cj ");
		sb.append("    INNER JOIN ruta              r ON ( cj.ruta_id = r.ruta_id )                                                                             ");
		sb.append("    LEFT JOIN grupo_ruta         gr ON ( r.gruporuta_id = gr.gruporuta_id )                                                                  ");
		sb.append("    INNER JOIN ruta_combinacion  rc ON ( rc.ruta_id = cj.ruta_id                                                                             ");
		sb.append("                                        AND rc.activo = 1 )                                                                                  ");
		sb.append("    INNER JOIN corrida           co ON ( co.corrida_id = cj.corrida_id                                                                       ");
		sb.append("                                        AND co.ruta_id = r.ruta_id                                                                           ");
		sb.append("                                        AND co.activo = 1                                                                                    ");
		sb.append("                                        AND cj.feccorrida = co.feccorrida )                                                                  ");
		sb.append("    INNER JOIN tramo             tr ON ( tr.tramo_id = rc.tramo_id                                                                           ");
		sb.append("                                        AND tr.origen_id = co.origen_id                                                                      ");
		sb.append("                                        AND tr.destino_id = co.destino_id )                                                                  ");
		sb.append("    INNER JOIN marca             m ON ( cj.marca_id = m.marca_id                                                                             ");
		sb.append("                                        AND m.empresa_id = :empresaId )                                                                      ");
		sb.append("    INNER JOIN empresa           e ON ( e.empresa_id = :empresaId )                                                                          ");
		sb.append("    INNER JOIN parada            origen ON ( origen.parada_id = tr.origen_id )                                                               ");
		sb.append("    INNER JOIN parada            destino ON ( destino.parada_id = tr.destino_id )                                                            ");
		sb.append("    INNER JOIN corridas_count    cos ON ( cos.corrida_id = co.corrida_id 																	");
		sb.append(" 									  AND cos.tiposervicio_id = co.tiposervicio_id                                                          ");
		sb.append("                                       AND hora = to_char(co.fechorsalida, 'HH24:MI') )                                                      ");
		sb.append("WHERE                                                                                                                                        ");
		sb.append("        cj.activo = 1                                                                                                                        ");
		sb.append("    AND cj.motivocancelacion_id IS NULL                                                                                                      ");
		sb.append("    AND cj.indstatusboleto = 'V'                                                                                                             ");
		sb.append("        and cj.feccorrida BETWEEN TO_DATE(:DATA_INICIO, 'DD/MM/YY hh24:mi:ss') AND TO_DATE(:DATA_FINAL, 'DD/MM/YY hh24:mi:ss') 				");
		sb.append(rutaIds == null ||TODOS.equals(rutaIds) ? "" : "   AND    r.ruta_id IN (   " + rutaIds + "   )     											");
		sb.append(corridasIds == null || TODOS.equals(corridasIds)	 ? "" : "   AND    cj.corrida_id IN (   " + corridasIds + "   )     						");
		sb.append(grupoRutaId == null || TODOS.equals(grupoRutaId) ? "" : "   AND    R.GRUPORUTA_ID IN (   " + grupoRutaId + "   )     							");
		sb.append("GROUP BY                                                                                                                                     ");
		sb.append("    cj.caja_id,                                                                                                                              ");
		sb.append("    cj.corrida_id,                                                                                                                           ");
		sb.append("    r.ruta_id,                                                                                                                               ");
		sb.append("    r.descruta,                                                                                                                              ");
		sb.append("    r.indsentidoida,                                                                                                                         ");
		sb.append("    nvl(e.indiceirk, 0),                                                                                                                     ");
		sb.append("    nvl(gr.descgrupo, 'Nao Definido'),                                                                                                       ");
		sb.append("    cj.importeseguro,                                                                                                                        ");
		sb.append("    cj.importetaxaembarque,                                                                                                                  ");
		sb.append("    cj.importepedagio,                                                                                                                       ");
		sb.append("    cj.preciopagado,                                                                                                                         ");
		sb.append("    r.prefixo,                                                                                                                               ");
		sb.append("    cos.hora,                                                                                                                                ");
		sb.append("    cos.quantidade,                                                                                                                          ");
		sb.append("    co.tiposervicio_id																														");
		sb.append("ORDER BY                                                                                                                                     ");
		sb.append("    r.descruta                                                                                                                               ");
		
		sb.append(" ) dados_sem_agrupamento    ");
		sb.append("   GROUP BY servico,        ");
		sb.append("            rutaid,         ");
		sb.append("            descruta,       ");
		sb.append("            gruporuta,      ");
		sb.append("            sentido,        ");
		sb.append("            indiceirkminimo,");
		sb.append("            hora,");
		sb.append("            extensao,");
		sb.append("            prefixo,");
		sb.append("            qtdCorrida, ");
		sb.append("            tipo_servico ");
		sb.append("   ORDER BY descruta, ");
		sb.append("            hora)tabela ");
		sb.append("GROUP BY servico,");
		sb.append("         rutaid,");
		sb.append("         descruta,");
		sb.append("         sentido,");
		sb.append("         gruporuta,");
		sb.append("         indiceirkminimo,");
		sb.append("         hora,");
		sb.append("         prefixo, ");
		sb.append("         passageiros, ");
		sb.append("         CASE WHEN tipo_servico = 1  THEN 'O' WHEN tipo_servico = 2  THEN 'E' END ");
		sb.append("ORDER BY descruta,");
		sb.append("         sentido,");
		sb.append("         hora");

		return sb.toString();

	}

	private List<RelatorioIndiceIRKBean> preencheAgrupaRelatorioBean(ResultSet rset, Map<String, Object> parametros) throws SQLException {
		
		lsDadosRelatorio = new ArrayList<RelatorioIndiceIRKBean>();
		
		while (rset.next()) {
			RelatorioIndiceIRKBean relatorioIndiceIRK = new RelatorioIndiceIRKBean();
			relatorioIndiceIRK.setServico((Integer) rset.getInt("servico"));
			relatorioIndiceIRK.setRutaId((Integer) rset.getInt("rutaid"));
			relatorioIndiceIRK.setDescRuta((String) rset.getObject("descruta"));
			relatorioIndiceIRK.setGrupoRuta((String) rset.getObject("gruporuta"));
			relatorioIndiceIRK.setSentido((String) rset.getString("sentido"));
			relatorioIndiceIRK.setIrkMinimo((BigDecimal) rset.getObject("indiceirkminimo"));
			relatorioIndiceIRK.setHora((String) rset.getObject("hora"));
			relatorioIndiceIRK.setExtensao((BigDecimal) rset.getObject("extensao"));
			relatorioIndiceIRK.setKmRodado(((BigDecimal) rset.getObject("extensao")));
			relatorioIndiceIRK.setSeguro((BigDecimal) rset.getObject("seguro"));
			relatorioIndiceIRK.setTxEmbarque((BigDecimal) rset.getObject("txembarque"));
			relatorioIndiceIRK.setPedagio((BigDecimal) rset.getObject("pedagio"));
			relatorioIndiceIRK.setPassagens((BigDecimal) rset.getObject("passagens"));
			relatorioIndiceIRK.setTotalViagem((BigDecimal) rset.getObject("totalhorario"));
			relatorioIndiceIRK.setTotal((BigDecimal) rset.getObject("totalhorario"));
			relatorioIndiceIRK.setIrk((BigDecimal) rset.getObject("irk"));
			relatorioIndiceIRK.setReceitaMinima((BigDecimal) rset.getObject("receitaminima"));
			relatorioIndiceIRK.setDiferencaReceitas((BigDecimal) rset.getObject("diferencareceita"));
			relatorioIndiceIRK.setPrefixoLinha((String) rset.getObject("prefixo"));
			relatorioIndiceIRK.setPassageiros((BigDecimal) rset.getObject("passageiros"));
			relatorioIndiceIRK.setTipoServico((String) rset.getObject("tipoServico"));

			lsDadosRelatorio.add(relatorioIndiceIRK);
		}
		
		return lsDadosRelatorio;
	}

}
