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.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
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.RelatorioMensalDAERBean;
import com.rjconsultores.ventaboletos.web.utilerias.NamedParameterStatement;

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

public class RelatorioMensalDAER extends Relatorio {

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

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

		this.setCustomDataSource(new DataSource(this) {
			@Override
			public void initDados() throws Exception {
				try {
					Integer agencia = parametros.get("AGENCIA") != null ? Integer.valueOf(parametros.get("AGENCIA").toString())  : null;
					Empresa empresa = parametros.get("EMPRESA") != null ? (Empresa) (parametros.get("EMPRESA")) : null;
					lsDadosRelatorio = preencheAgrupaRelatorioBean(preparaExecutaQuery(parametros, conexao, empresa, agencia, listCategoria));

					parametros.put("RELATORIOLIST", lsDadosRelatorio);
					setLsDadosRelatorio(lsDadosRelatorio);

				} catch (Exception e) {
					log.error("Erro ao executar relatório", e);
				}
			}

			/**
			 * @param parametros
			 * @param conexao
			 * @param agencia
			 * @param empresa
			 * @return
			 * @throws SQLException
			 */
			private ResultSet preparaExecutaQuery(Map<String, Object> parametros, Connection conexao, Empresa empresa, Integer agencia, List<Integer> idsCorrida) throws SQLException {
				Boolean istipoVenta = (idsCorrida.size() > 0);
				StringBuilder sqlCat = new StringBuilder();
				sqlCat = getIdsCategoria(listCategoria);
				String sql = getSql(istipoVenta,sqlCat);
				NamedParameterStatement stmt = new NamedParameterStatement(conexao, sql);
				ResultSet rset = null;
				SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");

				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("EMPRESA", empresa.getEmpresaId());
				stmt.setInt("AGENCIA", agencia);
				rset = stmt.executeQuery();
				return rset;
			}

		});
	}

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

	protected List<RelatorioMensalDAERBean> preencheAgrupaRelatorioBean(ResultSet rset) throws SQLException {
		lsDadosRelatorio = new ArrayList<RelatorioMensalDAERBean>();
		Integer qtBilhetes = null;
		while (rset.next()) {
			RelatorioMensalDAERBean relatorioMensalDAER = new RelatorioMensalDAERBean(rset.getInt("corrida_id"));
			qtBilhetes = rset.getInt("qtdbilhetes");
			if (!lsDadosRelatorio.contains(relatorioMensalDAER) && !qtBilhetes.equals(0)) {
				String sentido = rset.getString("sentidoida").equals("0") ? "1" : "2";
				float manifbilhetes = rset.getFloat("manifbilhetes");
				BigDecimal comissaoDAER = BigDecimal.valueOf(manifbilhetes * (11.0f / 100.0f));
				float comissao = comissaoDAER.floatValue();
				BigDecimal taxaFiscal = BigDecimal.valueOf(comissao * (3.0f / 100.0f));

				relatorioMensalDAER.setFecHorSalida(retornaHora(rset.getTimestamp("partida"), true));
				relatorioMensalDAER.setFecMinSalida(retornaHora(rset.getTimestamp("partida"), false));
				relatorioMensalDAER.setFecHorInicio(retornaHora(rset.getTimestamp("inicio"), true));
				relatorioMensalDAER.setFecMinInicio(retornaHora(rset.getTimestamp("inicio"), false));
				relatorioMensalDAER.setFecCorrida(rset.getDate("feccorrida"));
				relatorioMensalDAER.setIndSentidoIda(sentido);
				relatorioMensalDAER.setNumRuta(rset.getString("linha"));
				relatorioMensalDAER.setModal(rset.getString("modal"));
				relatorioMensalDAER.setCatVeiculo(rset.getString("catVeiculo"));
				relatorioMensalDAER.setCodDER(rset.getInt("codemp"));
				relatorioMensalDAER.setQtdServNormal(rset.getInt("normal"));
				relatorioMensalDAER.setQtdServExtra(rset.getInt("extra"));
				relatorioMensalDAER.setQtdBilhetes(rset.getInt("qtdbilhetes"));
				relatorioMensalDAER.setManifBilhetes(rset.getBigDecimal("manifbilhetes"));
				relatorioMensalDAER.setEncomendas(null);
				relatorioMensalDAER.setComissaoPassagem(comissaoDAER);
				relatorioMensalDAER.setTaxaFiscalizacao(taxaFiscal);
				relatorioMensalDAER.setTaxaManutencao(rset.getBigDecimal("embarque"));

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

	}

	protected String getSql(Boolean existeTpCategoria, StringBuilder sqlCat) {
		StringBuilder sql = new StringBuilder();
		sql.append("SELECT ");
		sql.append("( case when  ct.numsecuencia = 1 then null ");
		sql.append("	 else (SELECT cot.fechorsalida FROM corrida cot ");
		sql.append("		   	INNER JOIN corrida_tramo ctt ON ( cot.corrida_id = ctt.corrida_id  AND cot.feccorrida = ctt.feccorrida AND ctt.activo = 1 ) ");
		sql.append("  			where cot.feccorrida = co.feccorrida and cot.corrida_id = co.corrida_id and ctt.numsecuencia = 1) END ) AS inicio, ");
		sql.append("	ct.fechorsalida     AS partida, ");
		sql.append("	co.feccorrida, ");
		sql.append("	co.corrida_id, ");
		sql.append("	 ct.numsecuencia, ");
		sql.append("	rut.indsentidoida    AS sentidoida, ");
		sql.append("	rut.numruta          AS linha, ");
		sql.append("	cs.claseservicio_id  AS modal, ");
		sql.append("	' ' as catVeiculo, ");
		sql.append("	e.codder             AS codemp, ");
		sql.append("	( SELECT COUNT(cn.corrida_id) FROM corrida cn WHERE cn.corrida_id = co.corrida_id AND cn.tiposervicio_id = 1 ");
		sql.append("	AND cn.feccorrida BETWEEN TO_DATE(:DATA_INICIO, 'DD/MM/YYYY') AND TO_DATE(:DATA_FINAL, 'DD/MM/YYYY')) as normal, ");
		sql.append("	( SELECT COUNT(ce.corrida_id) FROM corrida ce WHERE ce.corrida_id = co.corrida_id AND ce.tiposervicio_id = 2 ");
		sql.append("	AND ce.feccorrida BETWEEN TO_DATE(:DATA_INICIO, 'DD/MM/YYYY') AND TO_DATE(:DATA_FINAL, 'DD/MM/YYYY')) as extra, ");
		sql.append("	( SELECT COUNT(caja_id) FROM caja WHERE corrida_id = co.corrida_id AND ruta_id = co.ruta_id ");
		if (existeTpCategoria) {
			sql.append(sqlCat);                     
		}
		sql.append("	AND feccorrida BETWEEN TO_DATE(:DATA_INICIO, 'DD/MM/YYYY') AND TO_DATE(:DATA_FINAL, 'DD/MM/YYYY')) AS qtdbilhetes, ");
		sql.append("	( SELECT SUM(caja.preciobase+caja.importeseguro)FROM caja WHERE corrida_id = co.corrida_id AND ruta_id = co.ruta_id ");
		if (existeTpCategoria) {
			sql.append(sqlCat);       
		}
		sql.append("	AND feccorrida BETWEEN TO_DATE(:DATA_INICIO, 'DD/MM/YYYY') AND TO_DATE(:DATA_FINAL, 'DD/MM/YYYY')) AS manifbilhetes, ");
		sql.append("   ( SELECT SUM(caja.importetaxaembarque)FROM caja WHERE corrida_id = co.corrida_id AND ruta_id = co.ruta_id  ");
		if (existeTpCategoria) {
			sql.append(sqlCat);           
		}
		sql.append(" 		    AND feccorrida BETWEEN TO_DATE(:DATA_INICIO, 'DD/MM/YYYY') AND TO_DATE(:DATA_FINAL, 'DD/MM/YYYY')) AS embarque,  ");
		sql.append("	' ' as encomendas ");
		sql.append("FROM corrida co");
		sql.append("	INNER JOIN empresa 			e 	ON ( e.empresa_id = co.empresacorrida_id) ");
		sql.append("	INNER JOIN tipo_servicio  	ts 	ON ( ts.tiposervicio_id = co.tiposervicio_id) ");
		sql.append("	INNER JOIN corrida_tramo  	ct 	ON ( co.corrida_id = ct.corrida_id AND co.feccorrida = ct.feccorrida AND ct.activo = 1 ) ");
		sql.append("	INNER JOIN ruta           	rut ON ( rut.ruta_id = co.ruta_id AND rut.activo = 1 ) ");
		sql.append("	INNER JOIN ORGAO_CONCEDENTE oc 	ON (rut.ORGAOCONCEDENTE_ID = OC.ORGAOCONCEDENTE_ID) ");
		sql.append("	INNER JOIN clase_servicio 	cs  ON ( cs.claseservicio_id = co.claseservicio_id ) ");
		sql.append("	LEFT OUTER JOIN punto_venta pv 	ON ( pv.PARADA_ID = ct.origen_id ) ");
		sql.append("WHERE co.activo = 1	");
		sql.append("	AND cs.descclase in ('CONVENCIONAL', 'EXECUTIVO', 'SEMI-DIRETO')    ");
		sql.append("	AND oc.descorgao like '%DAER%' ");
		sql.append("	AND co.empresacorrida_id = :EMPRESA ");
		sql.append("	AND pv.puntoventa_Id =  :AGENCIA  ");
		sql.append("	AND co.feccorrida BETWEEN TO_DATE(:DATA_INICIO, 'DD/MM/YYYY') AND TO_DATE(:DATA_FINAL, 'DD/MM/YYYY') ");
		sql.append("ORDER BY ");
		sql.append("	co.corrida_id,	");
		sql.append("	rut.numruta, 	");
		sql.append("	ct.fechorsalida,");
		sql.append("    ct.numsecuencia	");

		return sql.toString();
	}

	private StringBuilder getIdsCategoria(List<Integer> lsCategoria) {
		Integer[] idsCategoria = new Integer[lsCategoria.size()];
		StringBuilder ids = new StringBuilder();
		int i = 0;
		for (Integer ec : lsCategoria) {
			idsCategoria[i] = ec;
			i++;
		}
		
		if (lsCategoria.size() >0) {
		ids.append(" AND caja.categoria_id in ( " + StringUtils.join(idsCategoria, ",") + ")");
		} else {
			ids.append("");
		}
		return ids;
	}
	
	public String retornaHora(Date horaCompleta, boolean ishora) {
		String horaMin = null;
		if (horaCompleta == null) {
			return horaMin;
		} else if (ishora) {
			SimpleDateFormat simpleTimeFormat = new SimpleDateFormat("HH");
			horaMin = simpleTimeFormat.format(horaCompleta);
			return horaMin;
		} else {
			SimpleDateFormat simpleTimeFormat = new SimpleDateFormat("mm");
			horaMin = simpleTimeFormat.format(horaCompleta);
			return horaMin;
		}

	}

	@Override
	protected void processaParametros() throws Exception {

	}

}
