package com.rjconsultores.ventaboletos.relatorios.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
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.Corrida;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.entidad.GrupoRuta;
import com.rjconsultores.ventaboletos.entidad.Ruta;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.DataSource;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.Relatorio;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.RelatorioLinhasHorarioBean;
import com.rjconsultores.ventaboletos.service.ConstanteService;
import com.rjconsultores.ventaboletos.web.utilerias.NamedParameterStatement;
import com.rjconsultores.ventaboletos.web.utilerias.spring.AppContext;

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

@SuppressWarnings({"unused", "unchecked"})
public class RelatorioLinhasHorarioSimplificado extends Relatorio {

	private static Logger log = LogManager.getLogger(RelatorioLinhasHorarioSimplificado.class);
	private List<RelatorioLinhasHorarioBean> lsDadosRelatorio;
	private static String CONSTANTE_GRATUIDADE_CRIANCA;

	public RelatorioLinhasHorarioSimplificado(Map<String, Object> parametros, Connection conexao) throws Exception {
		super(parametros, conexao);

		this.setCustomDataSource(new DataSource(this) {
			@Override
			public void initDados() throws Exception {

				CONSTANTE_GRATUIDADE_CRIANCA = buscarConstante("GRATUIDADE_CRIANCA");
				Connection conexao = this.relatorio.getConexao();
				Map<String, Object> parametros = this.relatorio.getParametros();

				ArrayList<Ruta> lsNumLinha = (ArrayList<Ruta>) parametros.get("lsNumLinha");
				ArrayList<Corrida> lsNumServico = (ArrayList<Corrida>) parametros.get("lsNumServico");
				parametros.put("SERVICO_FILTRO", retornaFiltro(lsNumServico, null));
				parametros.put("LINHA_FILTRO",  retornaFiltro(null, lsNumLinha));

				Empresa empresa = (Empresa) parametros.get("EMPRESA");
				String corridaIds = "", rutaIds = "";
				GrupoRuta grupoRuta = (GrupoRuta) parametros.get("GRUPORUTA");
				Integer tipoServico = (Integer) parametros.get("TIPOSERVICIO_ID");
				if (lsNumServico != null && !lsNumServico.isEmpty()) {
					corridaIds = retornaFiltro(lsNumServico, null);
				}
				if (lsNumLinha != null && !lsNumLinha.isEmpty()) {
					rutaIds = retornaFiltro(null, lsNumLinha);
				}
				String sql = getSql(corridaIds, rutaIds, empresa, tipoServico, grupoRuta, (Boolean)parametros.get("ISSENTIDOIDA"), (Boolean)parametros.get("ISSENTIDOVOLTA"));
				
				NamedParameterStatement stmt = new NamedParameterStatement(conexao, sql);
				ResultSet rset = null;
				stmt.setString("CRIANCA_ID",CONSTANTE_GRATUIDADE_CRIANCA);
				
				if (empresa != null) {
					stmt.setInt("EMPRESA_ID", empresa.getEmpresaId());
				}
				if (parametros.get("HORA_INICIAL") == 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));
					}
				}else {
					setaParametroDataHora(parametros, stmt);
				}
				if (grupoRuta != null) {
				    stmt.setInt("GRUPORUTA_ID", grupoRuta.getGrupoRutaId());
				}
				if (tipoServico > 0) {
				    stmt.setInt("TIPOSERVICIO_ID", tipoServico);
				}

				rset = stmt.executeQuery();

				lsDadosRelatorio = new ArrayList<RelatorioLinhasHorarioBean>();

				BigDecimal totalPassagens = BigDecimal.ZERO;
				BigDecimal totalSeguro = BigDecimal.ZERO;
				BigDecimal totalBagagens = BigDecimal.ZERO;
				BigDecimal totalSeuroOpcional = BigDecimal.ZERO;
				BigDecimal totalTotal = BigDecimal.ZERO;
				BigDecimal totalOrdinario = BigDecimal.ZERO;
				BigDecimal totalExtra = BigDecimal.ZERO;
				BigDecimal totalViagem = BigDecimal.ZERO;
				BigDecimal totalKmRodado = BigDecimal.ZERO;
				BigDecimal totalAbsoluto = BigDecimal.ZERO;
				BigDecimal totalEquivalente = BigDecimal.ZERO;
				BigDecimal mediaMPA = BigDecimal.ZERO;
				BigDecimal mediaMPE = BigDecimal.ZERO;
				BigDecimal mediaRsPorKm = BigDecimal.ZERO;
				BigDecimal totalEQ = BigDecimal.ZERO;
				BigDecimal mediaRSPorViagem = BigDecimal.ZERO;
				BigDecimal totalPaxKMOfertado = BigDecimal.ZERO;
				BigDecimal totalPaxKMTransportado = BigDecimal.ZERO;
				BigDecimal totalIAP = BigDecimal.ZERO;

				BigDecimal totalTxEmbarque = BigDecimal.ZERO;
				BigDecimal totalPedagio = BigDecimal.ZERO;

				String group = null;
				while (rset.next()) {
					RelatorioLinhasHorarioBean horarioBean = new RelatorioLinhasHorarioBean();

					group = ((String) rset.getObject("GRUPO_RUTA"));
					horarioBean.setGrupoRuta(group);
					horarioBean.setTipoLinha((String) rset.getObject("TIPO_LINHA"));
					horarioBean.setHora((String) rset.getObject("HORA"));
					horarioBean.setServico((BigDecimal) rset.getObject("SERVICO"));

					if (rset.getObject("SENTIDO") != null) {
						horarioBean.convetSentido((BigDecimal) rset.getObject("SENTIDO"));
					} else {
						horarioBean.convetSentido(null);
					}

					horarioBean.setLot((BigDecimal) rset.getObject("LOT"));
					horarioBean.setCla((String) rset.getObject("CLA"));
					horarioBean.setExtensao((BigDecimal) rset.getObject("EXTENSAO"));
//					horarioBean.setTarifa((BigDecimal) rset.getObject("TARIFA"));
					horarioBean.setPassagens((BigDecimal) rset.getObject("PASSAGENS"));
					horarioBean.setSeguro((BigDecimal) rset.getObject("SEGURO"));
					horarioBean.setBagagens((BigDecimal) rset.getObject("BAGAGENS"));

					horarioBean.setTxEmbarque((BigDecimal) rset.getObject("TX_EMBARQUE"));
					horarioBean.setPedagio((BigDecimal) rset.getObject("PEDAGIO"));

					// Substituir a coluna Seg. Opcional por Tx. Embarque
					horarioBean.setSegOpc(horarioBean.getTxEmbarque());

					horarioBean.setOrd((BigDecimal) rset.getObject("ORD"));
					horarioBean.setExtra((BigDecimal) rset.getObject("EXTRA"));
					horarioBean.setAbsol((BigDecimal) rset.getObject("ABSOL"));

					horarioBean.setOrigem((String) rset.getObject("ORIGEM"));
					horarioBean.setDestino((String) rset.getObject("DESTINO"));
					horarioBean.setSomaExtensaoTrecho((BigDecimal) rset.getObject("EXTENSAO_TRECHO"));
					horarioBean.setPaxKmTransportado((BigDecimal) rset.getObject("KM_REAL"));
					horarioBean.setDescRuta((String) rset.getObject("DESCRUTA"));
					horarioBean = trecho(horarioBean);

					horarioBean = calcTotal(horarioBean);
					horarioBean = calcMediaReceitaTotal(horarioBean);

					horarioBean = calcTotalViagem(horarioBean);
					horarioBean = calcKmRodado(horarioBean);
					horarioBean = calcEquivalente(horarioBean);
					horarioBean = calcMpa(horarioBean);
					horarioBean = calcMpe(horarioBean);
					horarioBean = calcRsKm(horarioBean);
					horarioBean = calcEq(horarioBean);
					horarioBean = calcRsViagem(horarioBean);
					horarioBean = calcPaxKmOfertado(horarioBean);
					horarioBean = calcIap(horarioBean);

					lsDadosRelatorio.add(horarioBean);

					totalPassagens = totalPassagens.add(horarioBean.getPassagens() != null ? horarioBean.getPassagens() : BigDecimal.ZERO);
					totalSeguro = totalSeguro.add(horarioBean.getSeguro() != null ? horarioBean.getSeguro() : BigDecimal.ZERO);
					totalBagagens = totalBagagens.add(horarioBean.getBagagens() != null ? horarioBean.getBagagens() : BigDecimal.ZERO);
					totalSeuroOpcional = totalSeuroOpcional.add(horarioBean.getSegOpc() != null ? horarioBean.getSegOpc() : BigDecimal.ZERO);
					totalTotal = totalTotal.add(horarioBean.getTotal() != null ? horarioBean.getTotal() : BigDecimal.ZERO);
					totalOrdinario = totalOrdinario.add(horarioBean.getOrd() != null ? horarioBean.getOrd() : BigDecimal.ZERO);
					totalExtra = totalExtra.add(horarioBean.getExtra() != null ? horarioBean.getExtra() : BigDecimal.ZERO);
					totalViagem = totalViagem.add(horarioBean.getTotalViagem() != null ? horarioBean.getTotalViagem() : BigDecimal.ZERO);
					totalKmRodado = totalKmRodado.add(horarioBean.getKmRodado() != null ? horarioBean.getKmRodado() : BigDecimal.ZERO);
					totalAbsoluto = totalAbsoluto.add(horarioBean.getAbsol() != null ? horarioBean.getAbsol() : BigDecimal.ZERO);
					totalEquivalente = totalEquivalente.add(horarioBean.getEquivalente() != null ? horarioBean.getEquivalente() : BigDecimal.ZERO);

					totalTxEmbarque = totalTxEmbarque.add(horarioBean.getTxEmbarque() != null ? horarioBean.getTxEmbarque() : BigDecimal.ZERO);
					totalPedagio = totalPedagio.add(horarioBean.getPedagio() != null ? horarioBean.getPedagio() : BigDecimal.ZERO);

					mediaMPA = mediaMPA.add(horarioBean.getMpa() != null ? horarioBean.getMpa() : BigDecimal.ZERO);
					mediaMPE = mediaMPE.add(horarioBean.getMpe() != null ? horarioBean.getMpe() : BigDecimal.ZERO);

					mediaRsPorKm = mediaRsPorKm.add(horarioBean.getRsKm() != null ? horarioBean.getRsKm() : BigDecimal.ZERO);

					totalEQ = totalEQ.add(horarioBean.getEq() != null ? horarioBean.getEq() : BigDecimal.ZERO);

					mediaRSPorViagem = mediaRSPorViagem.add(horarioBean.getRsViagem() != null ? horarioBean.getRsViagem() : BigDecimal.ZERO);

					totalPaxKMOfertado = totalPaxKMOfertado.add(horarioBean.getPaxKmOfertado() != null ? horarioBean.getPaxKmOfertado() : BigDecimal.ZERO);
					totalPaxKMTransportado = totalPaxKMTransportado.add(horarioBean.getPaxKmTransportado() != null ? horarioBean.getPaxKmTransportado() : BigDecimal.ZERO);

					totalIAP = totalIAP.add(horarioBean.getIap());

				}

				BigDecimal qtdeRegistros = new BigDecimal(lsDadosRelatorio.size());

				if (lsDadosRelatorio.size() > 0) {

					setLsDadosRelatorio(lsDadosRelatorio);
					parametros.put("TOTAL_PASSAGENS", totalPassagens);
					parametros.put("TOTAL_SEGURO", totalSeguro);
					parametros.put("TOTAL_BAGAGENS", totalBagagens);
					parametros.put("TOTAL_SEURO_OPCIONAL", totalSeuroOpcional);
					parametros.put("TOTAL_TOTAL", totalTotal);
					parametros.put("TOTAL_ORDINARIO", totalOrdinario);
					parametros.put("TOTAL_EXTRA", totalExtra);
					parametros.put("TOTAL_VIAGEM", totalViagem);
					parametros.put("TOTAL_KM_RODADO", totalKmRodado);
					parametros.put("TOTAL_ABSOLUTO", totalAbsoluto);
					parametros.put("TOTAL_EQUIVALENTE", totalEquivalente);
					parametros.put("MEDIA_MPA", mediaMPA);
					parametros.put("MEDIA_MPE", mediaMPE);
					parametros.put("MEDIA_RS_POR_KM", mediaRsPorKm);
					parametros.put("TOTAL_EQ", totalEQ);
					parametros.put("TOTAL_TX_EMBARQUE", totalTxEmbarque);
					parametros.put("TOTAL_PEDAGIO", totalPedagio);
					parametros.put("MEDIA_RS_POR_VIAGEM", mediaRSPorViagem);
					parametros.put("TOTAL_PAX_KM_OFERTADO", totalPaxKMOfertado);
					parametros.put("TOTAL_PAX_KM_TRANSPORTADO", totalPaxKMTransportado);
					parametros.put("TOTAL_IAP", totalIAP);

				}
			}
			
			private String retornaFiltro(ArrayList<Corrida> lsNumServico, ArrayList<Ruta> lsNumLinha) {
			    String filtro = "TODOS";
			    if (lsNumServico != null && !lsNumServico.isEmpty()) {
			        for (Corrida corrida : lsNumServico) {
			            if (lsNumServico.indexOf(corrida) == 0) {
			            	filtro = "'" + corrida.getId().getCorridaId();
						} else {
							filtro += "','" + corrida.getId().getCorridaId();
						}
			        }
			        return filtro.concat("'");
			    } else if (lsNumLinha != null && !lsNumLinha.isEmpty()) {
			        for (Ruta ruta : lsNumLinha) {
			            if (lsNumLinha.indexOf(ruta) == 0) {
			            	filtro = "'" + ruta.getRutaId();
						} else {
							filtro += "','" + ruta.getRutaId();
						}
			        }
			        return filtro.concat("'");
			    } else {
			        return filtro;
			    }
			}

		});

	}
	
	private void setaParametroDataHora(Map<String, Object> parametros, NamedParameterStatement stmt) throws SQLException {
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
		Calendar dataInicial = Calendar.getInstance();
		dataInicial.setTime((Date) parametros.get("DATA_INICIO"));
		Calendar horaInicialCal = Calendar.getInstance();
		horaInicialCal.setTime((Date) parametros.get("HORA_INICIAL"));
		mesclarDataHora(dataInicial, horaInicialCal);
		stmt.setString("DATA_INICIO", sdf.format(dataInicial.getTime()));
		if (parametros.get("HORA_FINAL") != null) {
			Calendar dataFinal = Calendar.getInstance();
			dataFinal.setTime((Date) parametros.get("DATA_FINAL"));
			Calendar horaFinalCal = Calendar.getInstance();
			horaFinalCal.setTime((Date) parametros.get("HORA_FINAL"));
			mesclarDataHora(dataFinal, horaFinalCal);
			stmt.setString("DATA_FINAL", sdf.format(dataFinal.getTime()));
		}else {
			Date dataFinal = (Date) parametros.get("DATA_FINAL");
			stmt.setString("DATA_FINAL", sdf.format(dataFinal));
		}
		
	}

	public List<RelatorioLinhasHorarioBean> getLsDadosRelatorio() {

		return lsDadosRelatorio;
	}

	public void setLsDadosRelatorio(List<RelatorioLinhasHorarioBean> lsDadosRelatorio) {
		this.setCollectionDataSource(new JRBeanCollectionDataSource(lsDadosRelatorio));
		this.lsDadosRelatorio = lsDadosRelatorio;
	}

	private RelatorioLinhasHorarioBean trecho(RelatorioLinhasHorarioBean horarioBean) {
		horarioBean.setTrecho(horarioBean.getOrigem() + " - " + horarioBean.getDestino());
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcTotal(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal total = horarioBean.getPassagens();
		total = total.add(horarioBean.getSeguro());
		horarioBean.setTotal(total);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcMediaReceitaTotal(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal mediaTotal = horarioBean.getPassagens();
		horarioBean.setMediaReceitaViagem(mediaTotal);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcTotalViagem(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal totalViagem = horarioBean.getOrd().add(horarioBean.getExtra());
		horarioBean.setTotalViagem(totalViagem);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcKmRodado(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal kmRodado = horarioBean.getTotalViagem().multiply(horarioBean.getExtensao());
		horarioBean.setKmRodado(kmRodado);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcEquivalente(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal equivalente = new BigDecimal(0);
		try {
			equivalente = horarioBean.getSomaExtensaoTrecho().divide(horarioBean.getExtensao(), 2, RoundingMode.HALF_UP);
		} catch (ArithmeticException e) {
			equivalente = BigDecimal.ZERO;
		} catch (NullPointerException nex) {
			equivalente = BigDecimal.ZERO;
		} catch (Exception ex) {
			log.error("", ex);
		}
		horarioBean.setEquivalente(equivalente);

		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcMpa(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal mpa = new BigDecimal(0);
		try {
			mpa = horarioBean.getAbsol().divide(horarioBean.getTotalViagem(), 2, 4);
		} catch (ArithmeticException e) {
			mpa = BigDecimal.ZERO;
		} catch (NullPointerException nex) {
			mpa = BigDecimal.ZERO;
		} catch (Exception ex) {
			log.error("", ex);
		}
		horarioBean.setMpa(mpa);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcMpe(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal mpe = horarioBean.getEquivalente().divide(horarioBean.getTotalViagem(), 2, 4);
		horarioBean.setMpe(mpe);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcRsKm(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal rsKm = horarioBean.getTotal().divide(horarioBean.getKmRodado(), 2, 4);
		horarioBean.setRsKm(rsKm);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcEq(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal eq = null;
		try {
			eq = horarioBean.getMediaReceitaViagem().divide(horarioBean.getTarifa(), 2, 4);
		} catch (ArithmeticException e) {
			eq = BigDecimal.ZERO;
		} catch (NullPointerException nex) {
			eq = BigDecimal.ZERO;
		} catch (Exception ex) {
			log.error("", ex);
		}
		horarioBean.setEq(eq);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcRsViagem(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal RSViagem = horarioBean.getPassagens().divide(horarioBean.getTotalViagem(), 2, 4);
		horarioBean.setRsViagem(RSViagem);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcPaxKmOfertado(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal paxKmOfertado = horarioBean.getLot().multiply(horarioBean.getTotalViagem());
		paxKmOfertado = paxKmOfertado.multiply(horarioBean.getExtensao());
		horarioBean.setPaxKmOfertado(paxKmOfertado);
		return horarioBean;
	}

	private RelatorioLinhasHorarioBean calcIap(RelatorioLinhasHorarioBean horarioBean) {
		BigDecimal iap = null;
		BigDecimal CENTO = BigDecimal.TEN.multiply(BigDecimal.TEN);
		try {
			iap = (horarioBean.getPaxKmTransportado().multiply(CENTO)).divide(horarioBean.getPaxKmOfertado(), 2, 4);
		} catch (ArithmeticException e) {
			iap = BigDecimal.ZERO;
		} catch (NullPointerException nex) {
			iap = BigDecimal.ZERO;
		} catch (Exception ex) {
			log.error("", ex);
		}
		horarioBean.setIap(iap);
		return horarioBean;
	}

	private BigDecimal calcTotalIap(BigDecimal totalPaxKMTransportado, BigDecimal totalPaxKMOfertado) {
		BigDecimal iap = null;
		BigDecimal CENTO = BigDecimal.TEN.multiply(BigDecimal.TEN);
		try {
			iap = (totalPaxKMTransportado.multiply(CENTO)).divide(totalPaxKMOfertado, 2, 4);
		} catch (ArithmeticException e) {
			iap = BigDecimal.ZERO;
		} catch (NullPointerException nex) {
			iap = BigDecimal.ZERO;
		} catch (Exception ex) {
			log.error("", ex);
		}
		return iap;
	}

	@Override
	protected void processaParametros() throws Exception {
	}

	private String getSql(String corridaIds, String rutaIds, Empresa empresa, Integer tipoServico,
										GrupoRuta grupoRuta, Boolean isSentidoIda, Boolean isSentidoVolta) {

		StringBuilder sql = new StringBuilder();
		sql.append("with tb2 as (                                                                                           ");
		sql.append("      select /*+ materialize */                                                                         ");
		sql.append("        c.corrida_id,                                                                                   ");
		sql.append("        c.ruta_id                          as c_ruta_id,                                                ");
		sql.append("        destino.cveparada                  as destino,                                                  ");
		sql.append("        origem.cveparada                   as origem,                                                   ");
		sql.append("        c.roloperativo_id,                                                                              ");
		sql.append("        to_char(c.fechorsalida, 'HH24:MI') as horasalida,                                               ");
		sql.append("        count(case when c.tiposervicio_id = 1 then 1 else null end) as ord,                              ");
		sql.append("        count(case when c.tiposervicio_id = 2 then 1 else null end) as extra                             ");
		sql.append("      from corrida c                                                                                    ");
		sql.append("        inner join parada origem on c.origen_id = origem.parada_id                                      ");
		sql.append("        inner join parada destino on c.destino_id = destino.parada_id                                   ");
		sql.append(empresa == null ? "" : "inner join marca  m on (c.marca_id = m.marca_id and m.empresa_id = :EMPRESA_ID)  ");
		sql.append("      where                                                                                             ");
		sql.append("        exists (select 1 from caja ca where ca.corrida_id = c.corrida_id                                ");
		sql.append("							and ca.feccorrida = c.feccorrida                                            ");
		sql.append("							and ca.motivocancelacion_id is null)                                        ");
		sql.append("        and c.feccorrida between to_date(:DATA_INICIO, 'DD/MM/YYYY hh24:mi:ss') 						");
		sql.append("    	and to_date(:DATA_FINAL, 'DD/MM/YYYY hh24:mi:ss')       										");
		sql.append(tipoServico == 0 ? "" : "     and c.TIPOSERVICIO_ID = :TIPOSERVICIO_ID									");
		sql.append(rutaIds.isEmpty()  ? "" : " 	 and c.RUTA_ID  IN  (" + rutaIds + ")										");
		sql.append(corridaIds.isEmpty() ? "" : " and c.CORRIDA_ID IN (" + corridaIds + ")									"); 
		sql.append("      group by                                                                                          ");
		sql.append("        c.corrida_id,                                                                                   ");
		sql.append("        c.roloperativo_id,                                                                              ");
		sql.append("        c.ruta_id,                                                                                      ");
		sql.append("        destino.cveparada,                                                                              ");
		sql.append("        origem.cveparada,                                                                               ");
		sql.append("        to_char(c.fechorsalida, 'HH24:MI')                                                              ");
		sql.append("    ),                                                                                                  ");
		sql.append("tb4 as (                                                                                                ");
		sql.append("      select /*+ materialize */                                                                         ");
		sql.append("        c.corrida_id,                                                                                   ");
		sql.append("          c.ruta_id                          as c_ruta_id,                                              ");
		sql.append("          c.roloperativo_id,                                                                            ");
		sql.append("          c.destino_id,                                                                                 ");
		sql.append("          c.origen_id,                                                                                  ");
		sql.append("          to_char(c.fechorsalida, 'HH24:MI') as horasalida,                                             ");
		sql.append("          count(b.boleto_id)                 as absol                                                   ");
		sql.append("        from corrida c                                                                                  ");
		sql.append(empresa == null ? "" : " inner join marca  m on ( c.marca_id = m.marca_id and m.empresa_id = :EMPRESA_ID)"); 
		sql.append("          left join boleto b on ( b.corrida_id = c.corrida_id                                           ");
		sql.append("                                  and b.feccorrida = c.feccorrida                                       ");
		sql.append("                                  and b.activo = 1                                                      ");
		sql.append("                                  and b.motivocancelacion_id is null                                    ");
		sql.append("                                  and b.categoria_id <> :CRIANCA_ID )                                   ");
		sql.append("        where                                                                                           ");
		sql.append("          c.activo not in ( 0, 2 )                                                                      ");
		sql.append("          and c.feccorrida between to_date(:DATA_INICIO, 'DD/MM/YYYY hh24:mi:ss') 						");
		sql.append("    	and to_date(:DATA_FINAL, 'DD/MM/YYYY hh24:mi:ss')       										");
		sql.append(corridaIds.isEmpty() ? "" : " AND b.CORRIDA_ID IN (" + corridaIds + ") 									");
		sql.append("        group by                                                                                        ");
		sql.append("          c.corrida_id,                                                                                 ");
		sql.append("          c.ruta_id,                                                                                    ");
		sql.append("          c.roloperativo_id,                                                                            ");
		sql.append("          c.destino_id,                                                                                 ");
		sql.append("          c.origen_id,                                                                                  ");
		sql.append("          to_char(c.fechorsalida, 'HH24:MI')                                                            ");
		sql.append("      ),                                                                                                ");
		sql.append("  cj as (                                                                                               ");
		sql.append("        select /*+ materialize */                                                                       ");
		sql.append("          co.feccorrida,                                                                                ");
		sql.append("          co.corrida_id,                                                                                ");
		sql.append("          co.roloperativo_id,                                                                           ");
		sql.append("          co.ruta_id,                                                                                   ");
		sql.append("          co.empresacorrida_id,                                                                         ");
		sql.append("          bo.boleto_id,                                                                                 ");
		sql.append("          bo.numkmviaje * count(1)       as km_real,                                                    ");
		sql.append("          case when t.cantkmreal <> 0 and bo.numkmviaje <> 0 then                                       ");
		sql.append("			round(bo.numkmviaje * count(1) / t.cantkmreal, 3)                                           ");
		sql.append("            else 0 end                   as equivalente,                                                ");
		sql.append("          nvl(bo.importeseguro, 0)       as importeseguro,                                              ");
		sql.append("          nvl(bo.importetaxaembarque, 0) as importetaxaembarque,                                        ");
		sql.append("          nvl(bo.importepedagio, 0)      as importepedagio,                                             ");
		sql.append("          nvl(bo.preciopagado, 0)        as preciopagado                                                ");
		sql.append("        from corrida co                                                                                 ");
		sql.append(empresa == null ? "" : " inner join marca m on (co.marca_id = m.marca_id and m.empresa_id = :EMPRESA_ID) ");
		sql.append("          inner join boleto           bo on co.corrida_id = bo.corrida_id                               ");
		sql.append("                                  and co.feccorrida = bo.feccorrida                                     ");
		sql.append("                                  and bo.activo = 1                                                     ");
		sql.append("          inner join ruta_combinacion rc on rc.ruta_id = co.ruta_id                                     ");
		sql.append("          inner join tramo            t on rc.tramo_id = t.tramo_id                                     ");
		sql.append("                                and t.origen_id = bo.origen_id                                          ");
		sql.append("                                and t.destino_id = bo.destino_id                                        ");
		sql.append("        where                                                                                           ");
		sql.append("          co.activo not in ( 0, 2 )                                                                     ");
		sql.append(corridaIds.isEmpty() ? "" : " AND bo.CORRIDA_ID IN (" + corridaIds + ") 									");
		sql.append("          and rc.activo = 1                                                                             ");
		sql.append("          and t.activo = 1                                                                              ");
		sql.append("          and bo.indstatusboleto != 'S'                                                                 ");
		sql.append("          and bo.motivocancelacion_id is null                                                           ");
		sql.append("          and bo.categoria_id <> :CRIANCA_ID                                                            ");
		sql.append("          and bo.feccorrida between to_date(:DATA_INICIO, 'DD/MM/YYYY hh24:mi:ss') 						");
		sql.append("		  and to_date(:DATA_FINAL, 'DD/MM/YYYY hh24:mi:ss')  											");							
		sql.append("        group by                                                                                        ");
		sql.append("          co.feccorrida,                                                                                ");
		sql.append("          co.corrida_id,                                                                                ");
		sql.append("          co.roloperativo_id,                                                                           ");
		sql.append("          co.ruta_id,                                                                                   ");
		sql.append("          co.empresacorrida_id,                                                                         ");
		sql.append("          bo.numkmviaje,                                                                                ");
		sql.append("          bo.boleto_id,                                                                                 ");
		sql.append("          t.cantkmreal,                                                                                 ");
		sql.append("          nvl(bo.importeseguro, 0),                                                                     ");
		sql.append("          nvl(bo.importetaxaembarque, 0),                                                               ");
		sql.append("          nvl(bo.importepedagio, 0),                                                                    ");
		sql.append("          nvl(bo.preciopagado, 0)                                                                       ");
		sql.append("      ),                                                                                                ");
		sql.append("  tb5 as (                                                                                              ");
		sql.append("        select /*+ materialize */                                                                       ");
		sql.append("          rc.ruta_id,                                                                                   ");
		sql.append("          t.origen_id,                                                                                  ");
		sql.append("          t.destino_id,                                                                                 ");
		sql.append("          nvl(t.cantkmreal, 0) as extensao                                                              ");
		sql.append("        from ruta_combinacion rc                                                                        ");
		sql.append("          inner join tramo t on rc.tramo_id = t.tramo_id                                                ");
		sql.append("        where                                                                                           ");
		sql.append("          rc.activo = 1                                                                                 ");
		sql.append("      )                                                                                                 ");
		sql.append("select                                                                                                  ");
		sql.append("  grupo_ruta,                                                                                           ");
		sql.append("  hora,                                                                                                 ");
		sql.append("  descruta,                                                                                             ");
		sql.append("  servico,                                                                                              ");
		sql.append("  sentido,                                                                                              ");
		sql.append("  lot,                                                                                                  ");
		sql.append("  cla,                                                                                                  ");
		sql.append("  origem,                                                                                               ");
		sql.append("  destino,                                                                                              ");
		sql.append("  extensao,                                                                                             ");
		sql.append("  coalesce(sum(equivalente * extensao), 0) as extensao_trecho,                                          ");
		sql.append("  coalesce(bagagens, 0)                    as bagagens,                                                 ");
		sql.append("  coalesce(sum(seguro), 0)                 as seguro,                                                   ");
		sql.append("  coalesce(sum(tx_embarque), 0)            as tx_embarque,                                              ");
		sql.append("  coalesce(sum(pedagio), 0)                as pedagio,                                                  ");
		sql.append("  coalesce(sum(passagens), 0)              as passagens,                                                ");
		sql.append("  ord,                                                                                                  ");
		sql.append("  extra,                                                                                                ");
		sql.append("  tipo_linha,                                                                                           ");
		sql.append("  absol,                                                                                                ");
		sql.append("  coalesce(sum(km_real), 0)                as km_real                                                   ");
		sql.append("from                                                                                                    ");
		sql.append("  (                                                                                                     ");
		sql.append("    select                                                                                              ");
		sql.append("      r.ruta_id,                                                                                        ");
		sql.append("      r.descruta                         as descruta,                                                   ");
		sql.append("      nvl(gr.descgrupo, 'NÃ£o Definido') as grupo_ruta,                                                 ");
		sql.append("      to_char(c.fechorsalida, 'HH24:MI') as hora,                                                       ");
		sql.append("      c.corrida_id                       as servico,                                                    ");
		sql.append("      r.indsentidoida                    as sentido,                                                    ");
		sql.append("      da.cantasientos                    as lot,                                                        ");
		sql.append("      nvl(cs.descclase, '')              as cla,                                                        ");
		sql.append("      max(nvl(tf.preciooriginal, 0))     as tarifa,                                                     ");
		sql.append("      origem.cveparada                   as origem,                                                     ");
		sql.append("      destino.cveparada                  as destino,                                                    ");
		sql.append("      extensao                           as extensao,                                                   ");
		sql.append("      cj.equivalente                     as equivalente,                                                ");
		sql.append("      sum(ee.impingreso)                 as bagagens,                                                   ");
		sql.append("      cj.importeseguro                   as seguro,                                                     ");
		sql.append("      cj.importetaxaembarque             as tx_embarque,                                                ");
		sql.append("      cj.importepedagio                  as pedagio,                                                    ");
		sql.append("      cj.preciopagado                    as passagens,                                                  ");
		sql.append("      cj.boleto_id,                                                                                     ");
		sql.append("      tb2.ord,                                                                                          ");
		sql.append("      tb2.extra,                                                                                        ");
		sql.append("      case when co.estado_id <> cd.estado_id then                                                       ");
		sql.append("      'INTERESTADUAL' else 'INTERMUNICIPAL' end as tipo_linha,                                          ");
		sql.append("      absol,                                                                                            ");
		sql.append("      cj.km_real                         as km_real                                                     ");
		sql.append("    from corrida c                                                                                      ");
		sql.append("      inner join tb2 on ( ( tb2.corrida_id = c.corrida_id                                               ");
		sql.append("                   and tb2.c_ruta_id = c.ruta_id )                                                      ");
		sql.append("                 and tb2.roloperativo_id = c.roloperativo_id                                            ");
		sql.append("                 and tb2.horasalida = to_char(c.fechorsalida, 'HH24:MI') )                              ");
		sql.append("      inner join tb4 on ( ( tb4.corrida_id = c.corrida_id                                               ");
		sql.append("                   and tb4.c_ruta_id = c.ruta_id )                                                      ");
		sql.append("                 and c.destino_id = tb4.destino_id                                                      ");
		sql.append("                 and c.origen_id = tb4.origen_id                                                        ");
		sql.append("                 and tb4.roloperativo_id = c.roloperativo_id                                            ");
		sql.append("                 and tb4.horasalida = to_char(c.fechorsalida, 'HH24:MI') )                              ");
		sql.append("      left join cj on ( cj.corrida_id = c.corrida_id                                                    ");
		sql.append("                and cj.feccorrida = c.feccorrida                                                        ");
		sql.append("                and cj.roloperativo_id = c.roloperativo_id                                              ");
		sql.append("                and cj.ruta_id = c.ruta_id                                                              ");
		sql.append("                and cj.empresacorrida_id = c.empresacorrida_id )                                        ");
		sql.append("      inner join parada           origem on ( c.origen_id = origem.parada_id )                          ");
		sql.append("      inner join parada           destino on ( c.destino_id = destino.parada_id )                       ");
		sql.append("      inner join ciudad           co on ( co.ciudad_id = origem.ciudad_id )                             ");
		sql.append("      inner join ciudad           cd on ( cd.ciudad_id = destino.ciudad_id )                            ");
		sql.append("      inner join ruta             r on ( c.ruta_id = r.ruta_id )                                        ");
		sql.append("      left join grupo_ruta       gr on ( r.gruporuta_id = gr.gruporuta_id )                             ");
		sql.append("      left join rol_operativo    ro on ( c.roloperativo_id = ro.roloperativo_id )                       ");
		sql.append("      left join diagrama_autobus da on ( da.diagramaautobus_id = ro.diagramaautobus_id )                ");
		sql.append("      left join clase_servicio   cs on ( cs.claseservicio_id = c.claseservicio_id )                     ");
		sql.append("      left join evento_extra     ee on ( ee.corrida_id = c.corrida_id                                   ");
		sql.append("                                     and ee.feccorrida = c.feccorrida                                   ");
		sql.append("                                     and ee.tipoeventoextra_id = 1 )                                    ");
		sql.append("      left join tarifa           tf on ( tf.claseservicio_id = c.claseservicio_id                       ");
		sql.append("                               and tf.destino_id = c.destino_id                                         ");
		sql.append("                               and tf.origen_id = c.origen_id                                           ");
		sql.append("                               and tf.marca_id = c.marca_id                                             ");
		sql.append("                               and tf.ruta_id = c.ruta_id                                               ");
		sql.append("                               and r.orgaoconcedente_id = tf.orgaoconcedente_id )                       ");
		sql.append("      left join vigencia_tarifa  vtf on ( tf.vigenciatarifa_id = vtf.vigenciatarifa_id )                ");
		sql.append("      inner join tb5 on ( tb5.ruta_id = c.ruta_id                                                       ");
		sql.append("                 and tb5.origen_id = origem.parada_id                                                   ");
		sql.append("                 and tb5.destino_id = destino.parada_id )                                               ");
		sql.append("    where                                                                                               ");
		sql.append("      c.feccorrida between to_date(:DATA_INICIO, 'DD/MM/YYYY hh24:mi:ss') 								");
		sql.append("	  and to_date(:DATA_FINAL, 'DD/MM/YYYY hh24:mi:ss')           										");
		sql.append("      and ( tf.tarifa_id is null                                                                        ");
		sql.append("            or ( tf.tarifa_id is not null                                                               ");
		sql.append("                 and c.feccorrida between vtf.feciniciovigencia and vtf.fecfinvigencia ) )              ");
		sql.append("      and c.activo <> 0                                                                                 ");
		sql.append(corridaIds.isEmpty() ? "" : " AND c.CORRIDA_ID IN (" + corridaIds + ")									");
		sql.append(grupoRuta == null ? "" : " AND r.GRUPORUTA_ID IN ( :GRUPORUTA_ID ) 										");
		sql.append(rutaIds.isEmpty()  ? "" : " AND r.RUTA_ID  IN  (" + rutaIds + ")											");
		sql.append(tipoServico == 0 ? "" : "  AND   c.TIPOSERVICIO_ID = :TIPOSERVICIO_ID									");
				if(Boolean.TRUE.equals(isSentidoIda)) {
					sql.append("  AND   R.INDSENTIDOIDA =1 ");
				}
				
				if(Boolean.TRUE.equals(isSentidoVolta)) {
					sql.append("  AND   R.INDSENTIDOIDA = 0 ");
				}
		sql.append("      and origem.activo = 1                                                                             ");
		sql.append("      and destino.activo = 1                                                                            ");
		sql.append("      and tb2.origem = origem.cveparada                                                                 ");
		sql.append("      and tb2.destino = destino.cveparada                                                               ");
		sql.append("      and r.activo = 1                                                                                  ");
		sql.append("      and ro.activo = 1                                                                                 ");
		sql.append("      and da.activo = 1                                                                                 ");
		sql.append("      and cs.activo = 1                                                                                 ");
		sql.append("      and ( cj.boleto_id is not null )                                                                  ");
		sql.append("    group by                                                                                            ");
		sql.append("      r.ruta_id,                                                                                        ");
		sql.append("      r.descruta,                                                                                       ");
		sql.append("      nvl(gr.descgrupo, 'NÃ£o Definido'),                                                               ");
		sql.append("      to_char(c.fechorsalida, 'HH24:MI'),                                                               ");
		sql.append("      c.corrida_id,                                                                                     ");
		sql.append("      r.indsentidoida,                                                                                  ");
		sql.append("      da.cantasientos,                                                                                  ");
		sql.append("      cs.descclase,                                                                                     ");
		sql.append("      tb5.extensao,                                                                                     ");
		sql.append("      tb2.ord,                                                                                          ");
		sql.append("      tb2.extra,                                                                                        ");
		sql.append("      absol,                                                                                            ");
		sql.append("      co.estado_id,                                                                                     ");
		sql.append("      cd.estado_id,                                                                                     ");
		sql.append("      origem.cveparada,                                                                                 ");
		sql.append("      destino.cveparada,                                                                                ");
		sql.append("      cj.preciopagado,                                                                                  ");
		sql.append("      cj.importeseguro,                                                                                 ");
		sql.append("      cj.importetaxaembarque,                                                                           ");
		sql.append("      cj.importepedagio,                                                                                ");
		sql.append("      cj.equivalente,                                                                                   ");
		sql.append("      cj.km_real,                                                                                       ");
		sql.append("      cj.boleto_id                                                                                      ");
		sql.append("  )                                                                                                     ");
		sql.append("group by                                                                                                ");
		sql.append("  grupo_ruta,                                                                                           ");
		sql.append("  hora,                                                                                                 ");
		sql.append("  descruta,                                                                                             ");
		sql.append("  servico,                                                                                              ");
		sql.append("  sentido,                                                                                              ");
		sql.append("  lot,                                                                                                  ");
		sql.append("  cla,                                                                                                  ");
		sql.append("  origem,                                                                                               ");
		sql.append("  destino,                                                                                              ");
		sql.append("  extensao,                                                                                             ");
		sql.append("  bagagens,                                                                                             ");
		sql.append("  ord,                                                                                                  ");
		sql.append("  extra,                                                                                                ");
		sql.append("  tipo_linha,                                                                                           ");
		sql.append("  absol                                                                                                 ");
		sql.append("order by                                                                                                ");
		sql.append("  tipo_linha,                                                                                           ");
		sql.append("  grupo_ruta,                                                                                           ");
		sql.append("  descruta,                                                                                             ");
		sql.append("  servico,                                                                                              ");
		sql.append("  origem,                                                                                               ");
		sql.append("  destino                                                                                               ");

		return sql.toString();
	}

	
	private String buscarConstante(String nomeConstante) {
		ConstanteService constanteService = (ConstanteService) AppContext.getApplicationContext().getBean("constanteService");
		return constanteService.buscarPorNomeConstante(nomeConstante).getValorconstante();
	}
	
	protected void mesclarDataHora(Calendar pData, Calendar pHora) {
		pData.set(Calendar.HOUR_OF_DAY, pHora.get(Calendar.HOUR_OF_DAY));
		pData.set(Calendar.MINUTE, pHora.get(Calendar.MINUTE));
		pData.set(Calendar.SECOND, pHora.get(Calendar.SECOND));

	}
}
