package com.rjconsultores.ventaboletos.relatorios.impl;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

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

public class RelatorioQuadroDemonstrativoMovimentoPassageirosNovoLayout extends Relatorio {

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

		this.setCustomDataSource(new ArrayDataSource(this) {

			@SuppressWarnings("rawtypes")
			public void initDados() throws Exception {
				Connection conexao = this.relatorio.getConexao();
				Map<String, Object> parametros = this.relatorio.getParametros();
				String dataDe = (String) parametros.get("DATA_DE"), dataAte = (String) parametros.get("DATA_ATE"), linhasIds = null;
				Boolean isLinhas = false;
				Integer empresaId = null;
				List<Map<String,Object>> dadosOrdenados = new ArrayList<Map<String,Object>>();
				
				if (parametros.get("LINHAS") != null) {
					linhasIds = (String) parametros.get("LINHAS");
					isLinhas = true;
				}
				if (parametros.get("EMPRESA_IDS") != null) {
					empresaId = Integer.parseInt((String) parametros.get("EMPRESA_IDS"));
				}
				String sql = getSql(isLinhas);

				NamedParameterStatement ps = new NamedParameterStatement(conexao, sql.toString());
				SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
				
				ps.setInt("empresa_id", empresaId);
				if (isLinhas) {
					ps.setString("linhas_id", linhasIds);
				}
				ps.setTimestamp("dataIni", new java.sql.Timestamp(sdf.parse(dataDe).getTime()));
				ps.setTimestamp("dataFim", new java.sql.Timestamp(sdf.parse(dataAte).getTime()));
				ResultSet rset = ps.executeQuery();
				
				while (rset.next()) {
					boolean agrupar = false;
					Map<String, Object> dataResult = new HashMap<String, Object>();

					dataResult.put("tarifa", rset.getBigDecimal("tarifa"));
					dataResult.put("origem", rset.getString("origem"));
					dataResult.put("destino", rset.getString("destino"));
					dataResult.put("km", rset.getFloat("km"));
					dataResult.put("totalida", rset.getLong("totalida"));
					dataResult.put("totalvolta", rset.getLong("totalvolta"));
					dataResult.put("totalReceita", rset.getBigDecimal("totalReceita"));
					dataResult.put("numRuta",  rset.getString("numRuta"));

					for (Iterator iterator = dadosOrdenados.iterator(); iterator.hasNext();) {

						@SuppressWarnings("unchecked")
						Map<String, Object> map = (Map<String, Object>) iterator.next();
						String origem = map.get("origem").toString();
						String destino = map.get("destino").toString();
						String numRuta = map.get("numRuta").toString();
						BigDecimal tarifa = (BigDecimal) map.get("tarifa");
						
						Long ida = (Long) map.get("totalida");
						Long volta = (Long) map.get("totalvolta");
						BigDecimal total =  (BigDecimal) map.get("totalReceita");

						if (origem.equals(rset.getString("destino")) 
								&& destino.equals(rset.getString("origem")) 
									&& numRuta.equals(rset.getString("numRuta")) && (tarifa != null && MoneyHelper.isIgual(tarifa, rset.getBigDecimal("tarifa")))) {
							agrupar = true;
							if (ida == 0) {
								map.put("totalida", rset.getLong("totalida"));
								total = total.add(limpaNulo(rset.getBigDecimal("totalReceita")));
								map.put("totalReceita", total);
							}
							else {
								map.put("totalvolta", rset.getLong("totalvolta") + volta);
								total = total.add(limpaNulo(rset.getBigDecimal("totalReceita")));
								map.put("totalReceita", total);
							}

						}

					}
						
					if (!agrupar) {
						dadosOrdenados.add(dataResult);
					}

				}
				
				this.dados.addAll(ordenaListMap(dadosOrdenados));
				this.resultSet = rset;
			}
		});
	}
	
	@Override
	protected void processaParametros() throws Exception {
	}

	private String getSql(Boolean linhasIds) {
		StringBuilder sql = new StringBuilder();

		sql.append(" SELECT DISTINCT ");
		sql.append(" 	sum(b.preciopagado + b.importepedagio) AS totalReceita, ");
		sql.append(" 	tar.precio AS tarifa, ");
		sql.append(" 	e.nombempresa AS empresa, ");
		sql.append("	r.descruta AS linha, ");
		sql.append(" 	r.NUMRUTA, ");
		sql.append(" 	ori.descparada AS origem, ");
		sql.append(" 	des.descparada AS destino, ");
		sql.append(" 	MAX(tr.CANTKMREAL) AS km, ");
		sql.append(" 	COUNT( DISTINCT ");
		sql.append(" 	CASE ");
		sql.append(" 		WHEN(r.indsentidoida = 1) THEN b.boleto_id ");
		sql.append(" 	ELSE NULL ");
		sql.append(" 	END ");
		sql.append(" 		) AS totalida, ");
		sql.append(" 	COUNT( DISTINCT ");
		sql.append(" 		CASE ");
		sql.append(" 	WHEN(r.indsentidoida = 0) THEN b.boleto_id ");
		sql.append(" 		ELSE NULL ");
		sql.append(" 	END ");
		sql.append(" 	) AS totalvolta,   ");
		sql.append(" 	rc.rutacombinacion_id AS rutaCombinacionId, ");
		sql.append(" 	tri.numsecuencia, ");
		sql.append(" 	r.indsentidoida ");
		
		sql.append(" FROM ");
		sql.append(" 	boleto b ");
		sql.append(" 		JOIN empresa e ON ( e.empresa_id = b.empresacorrida_id ) 						");
		sql.append(" 		JOIN marca m ON ( m.empresa_id = b.empresacorrida_id ) 							");
		sql.append(" 		JOIN categoria ca ON ( b.categoria_id = ca.categoria_id ) 						");
		sql.append(" 		JOIN parada ori ON ( ori.parada_id = b.origen_id ) 								");
		sql.append(" 		JOIN parada des ON ( des.parada_id = b.destino_id ) 							");
		sql.append(" 		JOIN ruta r ON (r.ruta_id = b.ruta_id ) 										");
		sql.append(" 		JOIN RUTA_COMBINACION rc ON ( rc.ruta_id = r.ruta_id and rc.activo = 1 ) 		");
		sql.append(" 		INNER JOIN tramo tr ON ( tr.TRAMO_ID = rc.TRAMO_ID 								");
		sql.append("										AND tr.ORIGEN_ID = ori.PARADA_ID				");
		sql.append("										AND tr.DESTINO_ID = des.PARADA_ID				");
		sql.append("										AND tr.ACTIVO = 1 ) 							");
		sql.append(" 		JOIN clase_servicio cs ON ( b.claseservicio_id = cs.claseservicio_id ) 			");
		sql.append(" 		INNER JOIN vigencia_tarifa vt ON ( b.fechorventa BETWEEN vt.feciniciovigencia 	");
		sql.append("							AND vt.fecfinvigencia      				");
		sql.append(" 							AND vt.activo = 1 ) 					");
		sql.append(" 		INNER JOIN tarifa tar ON (  tar.ruta_id = b.ruta_id 		");
		sql.append(" 									AND tar.marca_id = m.marca_id 	");
		sql.append(" 									AND tar.claseservicio_id = b.claseservicio_id 		");
		sql.append(" 									AND tar.vigenciatarifa_id = vt.vigenciatarifa_id  	");
		sql.append(" 									AND tar.origen_id = b.origen_id  			");
		sql.append(" 									AND tar.destino_id = b.destino_id 			");
		sql.append(" 									AND tar.TRAMO_ID = tr.TRAMO_ID 				");
		sql.append(" 									AND tar.activo = 1 ) 						");
		sql.append(" 		LEFT JOIN corrida_tramo tri ON ( b.corrida_id = tri.corrida_id 			");
		sql.append(" 											AND tri.origen_id = b.origen_id		");
		sql.append(" 											AND b.feccorrida = tri.feccorrida	");
		sql.append(" 											AND tri.activo = 1  )  				");

		sql.append(" WHERE 	b.empresacorrida_id IN :empresa_id 	");

		sql.append(" AND b.motivocancelacion_id is null 		");

		if (linhasIds) {
			sql.append(" AND r.NUMRUTA = :linhas_id 			");
		}

		sql.append(" AND b.feccorrida BETWEEN :dataIni AND :dataFim ");

		sql.append(" GROUP BY 	");
		sql.append(" 		tar.precio, 	");
		sql.append(" 		e.nombempresa, 	");
		sql.append(" 		r.descruta, 	");
		sql.append(" 		r.numruta, 		");
		sql.append(" 		ori.descparada, ");
		sql.append(" 		des.descparada, ");
		sql.append(" 		rc.rutacombinacion_id, 	");
		sql.append(" 		tri.numsecuencia,");
		sql.append(" 		r.indsentidoida ");
		sql.append(" ORDER BY 	");
		sql.append("		r.indsentidoida DESC,	");
		sql.append("		tri.numsecuencia, 		");
		sql.append(" 		r.descruta,				");
		sql.append(" 		rc.rutacombinacion_id	");

		return sql.toString();
	}
	
	public List<Map<String, Object>> ordenaListMap(List<Map<String, Object>> dadosOrdenados) {
		
		List<Map<String, Object>> semelhancas = new ArrayList<Map<String,Object>>();
		for ( Map<String, Object> p : dadosOrdenados ) {
			String origem = p.get("origem").toString();
			
			for (Map<String, Object> dado : dadosOrdenados) {
				@SuppressWarnings("unchecked")
				Map<String, Object> map = (Map<String, Object>) dado;
				
				if (origem.equals(map.get("origem").toString()) && !semelhancas.contains(map) ) {
					semelhancas.add(map);
				}
				
			}
		
		}
		return semelhancas;
	}
	
	private BigDecimal limpaNulo( BigDecimal val ) {
		if( val == null ) {
			return BigDecimal.ZERO;
		}else {
			return val;
		}
	}

}
