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

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

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

import com.rjconsultores.ventaboletos.relatorios.utilitarios.ArrayDataSource;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.Relatorio;
import com.rjconsultores.ventaboletos.utilerias.DateUtil;
import com.rjconsultores.ventaboletos.web.utilerias.NamedParameterStatement;


public class RelatorioAproveitamentoFinanceiro extends Relatorio {

	private static Logger log = LogManager.getLogger(RelatorioAproveitamentoFinanceiro.class);

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

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

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

				StringBuilder sql = new StringBuilder();
				sql.append(" select TB.*, ");
				sql.append("  (SELECT                                                                     ");
				sql.append("     max (TF.PRECIO)                                                          ");
				sql.append("     FROM                                                                     ");
				sql.append("       CORRIDA CR,                                                            ");
				sql.append("       TRAMO TR,                                                              ");
				sql.append("       RUTA R,                                                                ");
				sql.append("       RUTA_COMBINACION RC,                                                   ");
				sql.append("       TARIFA TF,                                                             ");
				sql.append("       VIGENCIA_TARIFA VT                                                     ");
				sql.append("     WHERE                                                                    ");
				sql.append("     CR.CORRIDA_ID = TB.SERVICO                                               ");
				sql.append("     AND CR.FECCORRIDA BETWEEN :DATA_INICIAL and :DATA_FINAL                  ");
				sql.append("     AND CR.RUTA_ID = TB.RUTAID                                               ");
				sql.append("     AND CR.RUTA_ID = R.RUTA_ID AND R.ACTIVO = 1                              ");
				sql.append("     AND CR.RUTA_ID = RC.RUTA_ID AND RC.ACTIVO = 1                            ");
				sql.append("     AND RC.TRAMO_ID = TR.TRAMO_ID                                            ");
				sql.append("     AND TF.TRAMO_ID = TR.TRAMO_ID                                            ");
				sql.append("     AND TF.MARCA_ID = CR.MARCA_ID                                            ");
				sql.append("     AND TF.RUTA_ID = CR.RUTA_ID                                              ");
				sql.append("     AND TF.STATUSTARIFA = 'A'                                                ");
				sql.append("     AND CR.ACTIVO <> 0                                                       ");
				sql.append("     AND TF.ACTIVO = 1                                                        ");
				sql.append("     AND TR.ORIGEN_ID = CR.ORIGEN_ID                                          ");
				sql.append("     AND TR.DESTINO_ID = CR.DESTINO_ID                                        ");
				sql.append("     AND TF.VIGENCIATARIFA_ID = VT.VIGENCIATARIFA_ID                          ");
				sql.append("     AND TF.ORGAOCONCEDENTE_ID = R.ORGAOCONCEDENTE_ID                         ");				
				sql.append("     AND VT.ACTIVO = 1                                                        ");
				sql.append("     AND CR.FECCORRIDA BETWEEN VT.FECINICIOVIGENCIA AND VT.FECFINVIGENCIA     ");
				sql.append("     AND TF.CLASESERVICIO_ID = CR.CLASESERVICIO_ID                            ");
				sql.append("     ) TARIFA	                                              ");
				sql.append(" from ");
				sql.append(" ( ");
				sql.append(" select * from ( ");
				sql.append("  SELECT  ");
				sql.append("    r.DESCRUTA as linha,  ");
				sql.append("    r.NUMRUTA as numLinha,  ");
				sql.append("    r.ruta_id  as rutaid, ");
				sql.append("    count( c.boleto_id) as passageiros,  ");
				sql.append("    sum( coalesce(c.preciopagado, 0) )as valor, ");
				sql.append("    to_char( co.FECCORRIDA, 'D') as dia, ");
				// Quantidade de dias da semana diferente vendidas
				// "WW" Esse parâmetro para o to_char tras o dia da semana da data
				sql.append("    coalesce(count(DISTINCT to_char( co.FECCORRIDA, 'WW')), 0) as qtde, ");
				sql.append("    r.indsentidoida as sentido, ");
				sql.append("    da.cantasientos as assentos, ");
				sql.append("    TO_CHAR(co.fechorsalidaoriginal ,'HH24:mi') as horario, ");
				sql.append("    co.CORRIDA_ID as servico ");
				sql.append("  FROM boleto c ");
				sql.append("  RIGHT OUTER JOIN corrida co ");
				sql.append("    on c.CORRIDA_ID = co.CORRIDA_ID ");
				sql.append("    and c.FECCORRIDA = co.FECCORRIDA ");
				sql.append("    and co.ACTIVO = 1  ");
				sql.append("  inner join ruta r  ");
				sql.append("    on co.RUTA_ID = r.RUTA_ID ");
				sql.append("    and r.ACTIVO = 1 ");
				sql.append("  inner join MARCA m ");
				sql.append("    on m.marca_id = co.marca_id ");
				sql.append("    and m.activo = 1 ");
				sql.append("  left join rol_operativo ro ");
				sql.append("    on ro.roloperativo_id = co.roloperativo_id ");
			    sql.append("  left join diagrama_autobus da "); 
	    		sql.append("    on ro.diagramaautobus_id = da.diagramaautobus_id "); 
				sql.append("  WHERE co.activo = 1 ");
				sql.append("    AND c.activo = 1 ");
				sql.append("    AND m.EMPRESA_ID  = :EMPRESA_ID ");
				sql.append("    and co.FECCORRIDA >= :DATA_INICIAL ");
				sql.append("    and co.FECCORRIDA <= :DATA_FINAL ");
				
				if (parametros.get("LINHAS") != null && !possuiFiltroTodos("LINHAS")) {
					sql.append("    and co.ruta_id IN (" + parametros.get("LINHAS").toString() + ")");
				}
				
				sql.append("    and c.MOTIVOCANCELACION_ID is null ");
				sql.append("  GROUP by r.DESCRUTA,  r.ruta_id, r.indsentidoida, r.NUMRUTA, da.cantasientos, ");
				sql.append("      to_char( co.FECCORRIDA, 'D'), TO_CHAR(co.fechorsalidaoriginal ,'HH24:mi'), ");
				sql.append("      co.CORRIDA_ID ");
				sql.append("  ORDER by r.DESCRUTA, r.indsentidoida desc, to_char( co.FECCORRIDA, 'D') ");
				sql.append("  ) ");
				sql.append("PIVOT  ");
				sql.append("( ");
				sql.append("  max(valor) receita_ope, ");
				sql.append("  max(qtde) qtde,  ");
				sql.append("  max(passageiros) tot  ");
				sql.append("  for dia in ('1', '2', '3', '4', '5', '6', '7') ");
				sql.append(") ORDER BY numlinha,sentido desc,horario ");
				sql.append(") TB");

				NamedParameterStatement stmt = new NamedParameterStatement(conexao, sql.toString());

				stmt.setInt("EMPRESA_ID", Integer.valueOf(parametros.get("EMPRESA_ID").toString()));
				stmt.setTimestamp("DATA_INICIAL", new Timestamp(DateUtil.inicioFecha((Date) parametros.get("DATA_INICIAL")).getTime()));
				stmt.setTimestamp("DATA_FINAL", new Timestamp(DateUtil.fimFecha((Date) parametros.get("DATA_FINAL")).getTime()));

				ResultSet rset = stmt.executeQuery();
				
				rset.setFetchSize(500);

				while (rset.next()) {

					Map<String, Object> dataResult = new HashMap<String, Object>();

					dataResult.put("LINHA", rset.getString("linha"));
					dataResult.put("NUMLINHA", rset.getString("numLinha"));
					dataResult.put("SENTIDO", rset.getString("sentido"));
					dataResult.put("SERVICO", rset.getString("servico"));
					dataResult.put("HORARIO", rset.getString("horario"));
					//Quantidade de assentos do diagrana autobus
					BigDecimal assentos = limpaNulo(rset.getBigDecimal("assentos"));
					BigDecimal tarifa = limpaNulo(rset.getBigDecimal("tarifa"));
					BigDecimal totPassageiros = BigDecimal.ZERO;
					BigDecimal totReceita = BigDecimal.ZERO;
					Integer viagens =0;
					
					BigDecimal segReceitaOpe = limpaNulo(rset.getBigDecimal("'2'_RECEITA_OPE"));
					Integer segQtde = rset.getInt("'2'_QTDE");
					BigDecimal segTot = limpaNulo(rset.getBigDecimal("'2'_TOT"));
					totPassageiros = totPassageiros.add(segTot);
					totReceita = totReceita.add(segReceitaOpe);
					viagens = viagens + segQtde;
					
					BigDecimal terReceitaOpe = limpaNulo(rset.getBigDecimal("'3'_RECEITA_OPE"));
					Integer terQtde = rset.getInt("'3'_QTDE");
					BigDecimal terTot = limpaNulo(rset.getBigDecimal("'3'_TOT"));
					totPassageiros = totPassageiros.add(terTot);
					totReceita = totReceita.add(terReceitaOpe);
					viagens = viagens .intValue() + terQtde.intValue();
					
					BigDecimal quaReceitaOpe = limpaNulo(rset.getBigDecimal("'4'_RECEITA_OPE"));
					Integer quaQtde = rset.getInt("'4'_QTDE");
					BigDecimal quaTot = limpaNulo(rset.getBigDecimal("'4'_TOT"));
					totPassageiros = totPassageiros.add(quaTot);
					totReceita = totReceita.add(quaReceitaOpe);
					viagens = viagens.intValue() + quaQtde.intValue();
					
					BigDecimal quiReceitaOpe = limpaNulo(rset.getBigDecimal("'5'_RECEITA_OPE"));
					Integer quiQtde = rset.getInt("'5'_QTDE");
					BigDecimal quiTot = limpaNulo(rset.getBigDecimal("'5'_TOT"));
					totPassageiros = totPassageiros.add(quiTot);
					totReceita = totReceita.add(quiReceitaOpe);
					viagens = viagens.intValue() + quiQtde.intValue();
					
					BigDecimal sexReceitaOpe = limpaNulo(rset.getBigDecimal("'6'_RECEITA_OPE"));
					Integer sexQtde = rset.getInt("'6'_QTDE");
					BigDecimal sexTot = limpaNulo(rset.getBigDecimal("'6'_TOT"));
					totPassageiros = totPassageiros.add(sexTot);
					totReceita = totReceita.add(sexReceitaOpe);
					viagens = viagens.intValue() + sexQtde.intValue();
					
					BigDecimal sabReceitaOpe = limpaNulo(rset.getBigDecimal("'7'_RECEITA_OPE"));
					Integer sabQtde = rset.getInt("'7'_QTDE");
					BigDecimal sabTot = limpaNulo(rset.getBigDecimal("'7'_TOT"));
					totPassageiros = totPassageiros.add(sabTot);
					totReceita = totReceita.add(sabReceitaOpe);
					viagens = viagens.intValue() + sabQtde.intValue();
					
					BigDecimal domReceitaOpe = limpaNulo(rset.getBigDecimal("'1'_RECEITA_OPE"));
					Integer domQtde = rset.getInt("'1'_QTDE");
					BigDecimal domTot = limpaNulo(rset.getBigDecimal("'1'_TOT"));
					totPassageiros = totPassageiros.add(domTot);
					totReceita = totReceita.add(domReceitaOpe);
					viagens = viagens.intValue() + domQtde.intValue();
					dataResult.put("VIAGENS", new BigDecimal(viagens));
					log.info("VIAGENS: " + viagens );
					dataResult.put("ASSENTOS", assentos);
					dataResult.put("TARIFA", tarifa);
					dataResult.put("TOT_PASSAGEIROS", totPassageiros);
					dataResult.put("TOT_RECEITA", totReceita);
					
					dataResult.put("SEG_RECEITA_OPE", segReceitaOpe);
					dataResult.put("SEG_QTDE", new BigDecimal(segQtde));
					dataResult.put("SEG_TOT", segTot);
					dataResult.put("SEG_FIN", calculaMedia(segReceitaOpe, tarifa, segQtde, assentos));
					
					dataResult.put("TER_RECEITA_OPE", terReceitaOpe);
					dataResult.put("TER_QTDE", new BigDecimal(terQtde));
					dataResult.put("TER_TOT", terTot);
					dataResult.put("TER_FIN", calculaMedia(terReceitaOpe, tarifa, terQtde, assentos));
					
					dataResult.put("QUA_RECEITA_OPE", quaReceitaOpe);
					dataResult.put("QUA_QTDE", new BigDecimal(quaQtde));
					dataResult.put("QUA_TOT", quaTot);
					dataResult.put("QUA_FIN", calculaMedia(quaReceitaOpe, tarifa, quaQtde, assentos));
					
					dataResult.put("QUI_RECEITA_OPE", quiReceitaOpe);
					dataResult.put("QUI_QTDE", new BigDecimal(quiQtde));
					dataResult.put("QUI_TOT", quiTot);
					dataResult.put("QUI_FIN", calculaMedia(quiReceitaOpe, tarifa, quiQtde, assentos));
					
					dataResult.put("SEX_RECEITA_OPE", sexReceitaOpe);
					dataResult.put("SEX_QTDE", new BigDecimal(sexQtde));
					dataResult.put("SEX_TOT", sexTot);
					dataResult.put("SEX_FIN", calculaMedia(sexReceitaOpe, tarifa, sexQtde, assentos));
					
					dataResult.put("SAB_RECEITA_OPE", sabReceitaOpe);
					dataResult.put("SAB_QTDE", new BigDecimal(sabQtde));
					dataResult.put("SAB_TOT", sabTot);
					dataResult.put("SAB_FIN", calculaMedia(sabReceitaOpe, tarifa, sabQtde, assentos));
					
					dataResult.put("DOM_RECEITA_OPE", domReceitaOpe);
					dataResult.put("DOM_QTDE", new BigDecimal(domQtde));
					dataResult.put("DOM_TOT", domTot);
					dataResult.put("DOM_FIN", calculaMedia(domReceitaOpe, tarifa, domQtde, assentos));

					this.dados.add(dataResult);
				}
				 
				this.resultSet = rset;
			}
		});
	}

	@Override
	protected void processaParametros() throws Exception {

	}
	
	
	private BigDecimal limpaNulo( BigDecimal val ) {
		if( val == null ) {
			return BigDecimal.ZERO;
		}else {
			return val;
		}
	}
	
	/**
	 * Faz calculo da media na seguinte formula (Tot. Rceita / (tarifa * qtde * assentos))
	 * (1427,17 / (108,30*1*42)) * 100
	 * @param totReceita
	 * @param tarifa
	 * @param qtde (Quantidade viagens do dia da semana no periodo. 
	 * Ex 01 a 07, sendo 01 Domingo e 07 Sabado, tera sempre quantidade igual a 7 se o servico for executado todo dia)
	 * @param tot 
	 * @return
	 */
	private BigDecimal calculaMedia(BigDecimal totReceita, BigDecimal tarifa, Integer qtde, BigDecimal tot) {
		if( qtde.intValue() != 0 && tot.intValue() !=0 ) {
			//Multiplica a tarifa pela quantidade de viagens no dia da semana (Segunda, terça...) no período
			BigDecimal dividendo = tarifa.multiply(new BigDecimal(qtde));
			//Multiplica o dividendo pelo total de passegeiros
			dividendo = dividendo.multiply(tot);
			
			if(dividendo.intValue() == 0 ) {
				return BigDecimal.ZERO;
			}
			
			BigDecimal fin = totReceita.divide(dividendo, 4, BigDecimal.ROUND_HALF_UP);
			fin = fin.multiply(new BigDecimal(new Long(100L))).setScale(2);
			return fin !=null ? fin : BigDecimal.ZERO;
		}else{
			return BigDecimal.ZERO;
		}
	}

}
