package com.rjconsultores.ventaboletos.relatorios.impl;

import java.sql.Connection;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

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

import org.apache.log4j.Logger;

import com.rjconsultores.ventaboletos.relatorios.utilitarios.DataSource;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.Relatorio;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.RelatorioVendasPacotesBoletosBean;
import com.rjconsultores.ventaboletos.web.utilerias.NamedParameterStatement;

public class RelatorioVendasBoletos extends Relatorio {
	
	private static Logger log = Logger.getLogger(RelatorioVendasBoletos.class);

	private SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
	
	private List<RelatorioVendasPacotesBoletosBean> lsDadosRelatorio;
	
	private Date fecInicio;
	private Date fecFinal;
	private Integer empresaId;
	private Integer origenId;
	private Integer destinoId;
	
	public RelatorioVendasBoletos(Map<String, Object> parametros, Connection conexao, final String... nomeSubReporte) throws Exception {
		super(parametros, conexao);
		
		this.setCustomDataSource(new DataSource(this) {


			@Override
			public void initDados() throws Exception {
				Map<String, Object> parametros = this.relatorio.getParametros();
				fecInicio = new java.sql.Date(sdf.parse(parametros.get("fecInicio").toString()).getTime());
				fecFinal = new java.sql.Date(sdf.parse(parametros.get("fecFinal").toString()).getTime());
				empresaId = parametros.get("empresaId") != null && !parametros.get("empresaId").equals("null") ? Integer.valueOf(parametros.get("empresaId").toString()) : null;
				origenId = parametros.get("origenId") != null && !parametros.get("origenId").equals("null") ? Integer.valueOf(parametros.get("origenId").toString()) : null;
				destinoId = parametros.get("destinoId") != null && !parametros.get("destinoId").equals("null") ? Integer.valueOf(parametros.get("destinoId").toString()) : null;
				
				Connection conexao = this.relatorio.getConexao();
				processarVendasPacote(conexao);
				processarVendasPacoteCancelados(conexao);
				
				setNomeSubReporte(nomeSubReporte);
				setLsDadosRelatorio(lsDadosRelatorio);
			}

		});
	}
	
	private void processarVendasPacote(Connection conexao) {
		ResultSet rset = null;
		NamedParameterStatement stmt = null;
		
		try {
			stmt = carregarNamedParameterStatement(conexao, false);
			rset = stmt.executeQuery();
	
			if(lsDadosRelatorio == null) {
				lsDadosRelatorio = new ArrayList<RelatorioVendasPacotesBoletosBean>();
			}
			
			while (rset.next()) {
				RelatorioVendasPacotesBoletosBean relatorioVendasBoletosBean = carregarRelatorioVendasBoletosBean(rset);
				Integer idx = carregarIndice(relatorioVendasBoletosBean);
				
				if(idx != null) {
					relatorioVendasBoletosBean = lsDadosRelatorio.get(idx); 
				}
				
				relatorioVendasBoletosBean.setRelatorioVendasPacotesBoletosItemBeans(carregarItens(rset, relatorioVendasBoletosBean, relatorioVendasBoletosBean.getRelatorioVendasPacotesBoletosItemBeans()));
				
				if(idx != null) {
					lsDadosRelatorio.set(idx, relatorioVendasBoletosBean);
				} else {
					lsDadosRelatorio.add(relatorioVendasBoletosBean);
				}
			}
			
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			try {
				if(rset != null) {
					rset.close();
				}
				if(stmt != null) {
					stmt.close();
				}
			} catch (SQLException e) {
				log.error(e.getMessage(), e);
			}
		}
		
	}
	
	private List<RelatorioVendasPacotesBoletosBean.RelatorioVendasPacotesBoletosItemBean> carregarItens(ResultSet rset, RelatorioVendasPacotesBoletosBean relatorioVendasPacotesBoletosBean, List<RelatorioVendasPacotesBoletosBean.RelatorioVendasPacotesBoletosItemBean> itens) throws SQLException {
		RelatorioVendasPacotesBoletosBean.RelatorioVendasPacotesBoletosItemBean relatorioVendasPacotesBoletosItemBean = relatorioVendasPacotesBoletosBean.new RelatorioVendasPacotesBoletosItemBean();
		relatorioVendasPacotesBoletosItemBean.setDesccategoria(rset.getString("desccategoria"));
		relatorioVendasPacotesBoletosItemBean.setQtde(rset.getLong("qtde"));
		relatorioVendasPacotesBoletosItemBean.setSimportetaxaembarque(rset.getBigDecimal("simportetaxaembarque"));
		relatorioVendasPacotesBoletosItemBean.setSimportepedagio(rset.getBigDecimal("simportepedagio"));
		relatorioVendasPacotesBoletosItemBean.setSimporteoutros(rset.getBigDecimal("simporteoutros"));
		relatorioVendasPacotesBoletosItemBean.setSimporteseguro(rset.getBigDecimal("simporteseguro"));
		relatorioVendasPacotesBoletosItemBean.setSpreciobase(rset.getBigDecimal("spreciobase"));
		relatorioVendasPacotesBoletosItemBean.setDesconto(rset.getBigDecimal("desconto"));
		
		if(itens == null) {
			itens = new ArrayList<RelatorioVendasPacotesBoletosBean.RelatorioVendasPacotesBoletosItemBean>();
		}
		itens.add(relatorioVendasPacotesBoletosItemBean);
		
		return itens;
	}

	private Integer carregarIndice(RelatorioVendasPacotesBoletosBean relatorioVendasBoletosBean) {
		Integer idx = null;
		if(lsDadosRelatorio.contains(relatorioVendasBoletosBean)) {
			idx = lsDadosRelatorio.indexOf(relatorioVendasBoletosBean);
			relatorioVendasBoletosBean = lsDadosRelatorio.get(idx);
		}
		return idx;
	}

	private RelatorioVendasPacotesBoletosBean carregarRelatorioVendasBoletosBean(ResultSet rset) throws SQLException {
		RelatorioVendasPacotesBoletosBean relatorioVendasPacotesBoletosBean = new RelatorioVendasPacotesBoletosBean();
		relatorioVendasPacotesBoletosBean.setDescdestino(rset.getString("destino"));
		relatorioVendasPacotesBoletosBean.setDescorigen(rset.getString("origem"));
		relatorioVendasPacotesBoletosBean.setCvedestino(rset.getString("cvedestino"));
		relatorioVendasPacotesBoletosBean.setCveorigen(rset.getString("cveorigem"));
		
		return relatorioVendasPacotesBoletosBean;
	}

	private void processarVendasPacoteCancelados(Connection conexao) {
		ResultSet rset = null;
		NamedParameterStatement stmt = null;
		
		try {
			stmt = carregarNamedParameterStatement(conexao, true);
			rset = stmt.executeQuery();
	
			if(lsDadosRelatorio == null) {
				lsDadosRelatorio = new ArrayList<RelatorioVendasPacotesBoletosBean>();
			}
			
			while (rset.next()) {
				RelatorioVendasPacotesBoletosBean relatorioVendasBoletosBean = carregarRelatorioVendasBoletosBean(rset);
				Integer idx = carregarIndice(relatorioVendasBoletosBean);
				
				if(idx != null) {
					relatorioVendasBoletosBean = lsDadosRelatorio.get(idx); 
				}
				
				relatorioVendasBoletosBean.setRelatorioVendasPacotesBoletosItemBeansCancelados(carregarItens(rset, relatorioVendasBoletosBean, relatorioVendasBoletosBean.getRelatorioVendasPacotesBoletosItemBeansCancelados()));
				
				if(idx != null) {
					lsDadosRelatorio.set(idx, relatorioVendasBoletosBean);
				} else {
					lsDadosRelatorio.add(relatorioVendasBoletosBean);
				}
			}
			
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			try {
				if(rset != null) {
					rset.close();
				}
				if(stmt != null) {
					stmt.close();
				}
			} catch (SQLException e) {
				log.error(e.getMessage(), e);
			}
		}
		
	}
	
	private NamedParameterStatement carregarNamedParameterStatement(Connection conexao, boolean cancelados) throws SQLException {
		String sql = getSqlPacotes(cancelados);
		log.info(sql);
		
		NamedParameterStatement stmt = new NamedParameterStatement(conexao, sql);
		
		if(fecInicio != null) {
			stmt.setDate("fecInicio", fecInicio);
		}
		if(fecFinal != null) {
			stmt.setDate("fecFinal", fecFinal);
		}
		if (empresaId != null){
			stmt.setInt("empresaId", empresaId);
		}
		if(origenId != null) {
			stmt.setInt("origenId", origenId);
		}
		if(destinoId != null) {
			stmt.setInt("destinoId", destinoId);
		}
		
		return stmt;
	}

	protected String getSqlPacotes(boolean cancelado) {
		StringBuilder sQuery = new StringBuilder();
		
		sQuery.append("SELECT DES.CVEPARADA AS CVEDESTINO, ORI.CVEPARADA AS CVEORIGEM, ORI.DESCPARADA AS ORIGEM, DES.DESCPARADA AS DESTINO, CAT.DESCCATEGORIA AS DESCCATEGORIA, ")
			  .append("COUNT(B.BOLETO_ID) AS QTDE, SUM(B.IMPORTETAXAEMBARQUE) AS SIMPORTETAXAEMBARQUE, SUM(B.IMPORTEPEDAGIO) AS SIMPORTEPEDAGIO, ")
			  .append("SUM(B.IMPORTEOUTROS) AS SIMPORTEOUTROS, SUM(B.IMPORTESEGURO) AS SIMPORTESEGURO, SUM(B.PRECIOBASE) AS SPRECIOBASE, SUM(B.PRECIOBASE - B.PRECIOPAGADO) AS DESCONTO ")
			  .append("FROM BOLETO B ")
			  .append("LEFT JOIN PARADA ORI ON ORI.PARADA_ID = B.ORIGEN_ID ")
			  .append("LEFT JOIN PARADA DES ON DES.PARADA_ID = B.DESTINO_ID ")
			  .append("LEFT JOIN CATEGORIA CAT ON CAT.CATEGORIA_ID = B.CATEGORIA_ID ")
			  .append("WHERE B.ACTIVO = 1 ");
		
		if(!cancelado) {
			sQuery.append("AND B.INDSTATUSBOLETO = 'V' ")
			  	  .append("AND B.MOTIVOCANCELACION_ID IS NULL ");
		} else {
			sQuery.append("AND B.MOTIVOCANCELACION_ID IS NOT NULL ");
		}
		
		if(empresaId != null) {
			sQuery.append("AND B.EMPRESACORRIDA_ID = :empresaId ");
		}

		if(origenId != null) {
			sQuery.append("AND B.ORIGEN_ID = :origenId ");
		}
		
		if(destinoId != null) {
			sQuery.append("AND B.DESTINO_ID = :destinoId ");
		}

		if(fecInicio != null) {
			sQuery.append("AND B.FECHORVENTA >= :fecInicio ");
		}
		
		if(fecFinal != null) {
			sQuery.append("AND B.FECHORVENTA <= :fecFinal ");
		}
		
		sQuery.append("GROUP BY DES.CVEPARADA, ORI.CVEPARADA, ORI.DESCPARADA, DES.DESCPARADA, CAT.DESCCATEGORIA ")
			  .append("ORDER BY DES.CVEPARADA, ORI.CVEPARADA, ORI.DESCPARADA, DES.DESCPARADA, CAT.DESCCATEGORIA ");
		
		return sQuery.toString();
	}
	
	@Override
	protected void processaParametros() throws Exception {
	}
	
	public List<RelatorioVendasPacotesBoletosBean> getLsDadosRelatorio() {
		return lsDadosRelatorio;
	}

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

}
