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

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.RelatorioVendasPTABean;
import com.rjconsultores.ventaboletos.web.utilerias.NamedParameterStatement;

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

public class RelatorioVendasPTA extends Relatorio {

	public RelatorioVendasPTA(Map<String, Object> parametros, Connection conexao) {
		super(parametros, conexao);
	}
	
	public enum SituacaoBoleto {

		TODAS(-1, "Todas", ""), ANULADO(31, "Anulado", "A"), DEVOLVIDO(32, "Devolvido", "D"), 
		REMARCADO(23, "Remarcado", "R"), TROCADO(10, "Trocado", "TP"), VENDIDO(1, "Vendido", ""), 
		ENTREGUE(2, "Entregue", ""), NAO_ENTREGUE(3, "Não Entregue", ""), CONTIGENCIA_100(37, "Contingencia 100%", "D");
		
		private String situacao;
		private Integer codigo;
		private String siglaCancelamento;

		private SituacaoBoleto(Integer codigo, String situacao, String siglaCancelamento) {
			this.situacao = situacao;
			this.codigo = codigo;
			this.siglaCancelamento = siglaCancelamento;
		}
		
		public String getSituacao() {
			return this.situacao;
		}
		
		public Integer getCodigo() {
			return codigo;
		}
		
		public String getSiglaCancelamento() {
			return this.siglaCancelamento;
		}
		
		public static SituacaoBoleto getSituacaoBoletoCancelado(Integer codigo) {
			for (SituacaoBoleto situacao : SituacaoBoleto.values()) {
				if (!situacao.siglaCancelamento.isEmpty() 
						&& situacao.getCodigo().equals(codigo)) {
					return situacao;
				}
			}
			throw new IllegalArgumentException("Situação de cancelamento inválido.");
		}
	}

	private List<RelatorioVendasPTABean> lsDadosRelatorio;

	@Override
	protected void processaParametros() throws Exception {

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

				Connection conexao = this.relatorio.getConexao();

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

				String dataInicial = parametros.get("DATA_INICIAL").toString() + " 00:00:00";
				String dataFinal = parametros.get("DATA_FINAL").toString() + " 23:59:59";
				Empresa empresa = (Empresa) parametros.get("EMPRESA");
				String agencia = (String) parametros.get("PUNTOVENTA");
				SituacaoBoleto situacaoBoleto = (SituacaoBoleto) parametros.get("SITUACAO_BOLETO");

				String sql = getSql(empresa, agencia, dataInicial, dataFinal, situacaoBoleto);

				NamedParameterStatement stmt = new NamedParameterStatement(conexao, sql);

				stmt.setTimestamp("DATA_INICIAL", (Timestamp) parametros.get("DATA_INICIAL"));
				stmt.setTimestamp("DATA_FINAL", (Timestamp) parametros.get("DATA_FINAL"));

				ResultSet rset = null;
				rset = stmt.executeQuery();

				lsDadosRelatorio = new ArrayList<RelatorioVendasPTABean>();
				BigDecimal saldo = BigDecimal.ZERO;
				BigDecimal total = BigDecimal.ZERO;

				while (rset.next()) {

					RelatorioVendasPTABean vendasPTABean = new RelatorioVendasPTABean();

					vendasPTABean.setPreco((BigDecimal) rset.getObject("preco"));
					vendasPTABean.setTaxas((BigDecimal) rset.getObject("taxas"));
					vendasPTABean.setBilhete((String) rset.getObject("bilhete"));
					vendasPTABean.setNomeAgenciaVenda((String) rset.getObject("nomeAgenciaVenda"));
					vendasPTABean.setAgencia((String) rset.getObject("agencia"));
					vendasPTABean.setStatus((String) rset.getObject("status"));
					vendasPTABean.setServico((BigDecimal) rset.getObject("servico"));
					vendasPTABean.setPoltrona((String) rset.getObject("poltrona"));
					vendasPTABean.setDescricaoLinha((String) rset.getObject("descricaoLinha"));
					vendasPTABean.setDescricaoOrigem((String) rset.getObject("descricaoOrigem"));
					vendasPTABean.setDescricaoDestino((String) rset.getObject("descricaoDestino"));
					vendasPTABean.setDataEmbarque((Date) rset.getObject("dataEmbarque"));
					vendasPTABean.setDataEmissao((Date) rset.getObject("dataEmissao"));
					vendasPTABean.setDataVenda((Date) rset.getObject("dataVenda"));

					if (vendasPTABean.getStatus().equals("VENDIDO")) {
						vendasPTABean.setSituacaoVendido("V");
						saldo = saldo.add(vendasPTABean.getPreco() != null ? vendasPTABean.getPreco() : BigDecimal.ZERO);
					} else {
						BigDecimal situacao = (BigDecimal) rset.getObject("situacaoCancelado");
						SituacaoBoleto situacaoBoletoCancelado;
						if (situacao != null
								&& (situacaoBoletoCancelado = SituacaoBoleto.getSituacaoBoletoCancelado(situacao.intValue())) != null) {
							vendasPTABean.setSituacaoCancelado(situacaoBoletoCancelado.getSiglaCancelamento());
						}

						total = total.add(vendasPTABean.getPreco() != null ? vendasPTABean.getPreco() : BigDecimal.ZERO);
					}

					lsDadosRelatorio.add(vendasPTABean);
				}

				if (lsDadosRelatorio.size() > 0) {

					setLsDadosRelatorio(lsDadosRelatorio);
					parametros.put("SALDO", saldo.subtract(total));
					parametros.put("TOTAL", total);
				}
			}
		});
	}

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

	private String getSql(Empresa empresa, String agencia, String fecInicio, String fecFinal, SituacaoBoleto situacaoBoleto) {

		StringBuilder sql = new StringBuilder();
		String motivoCancelacion = "";

		if (situacaoBoleto.getCodigo().equals(31)) {
			motivoCancelacion = "31";
		} else if (situacaoBoleto.getCodigo().equals(32)
				|| situacaoBoleto.getCodigo().equals(37)) {
			motivoCancelacion = "32, 37";
		} else if (situacaoBoleto.getCodigo().equals(23)) {
			motivoCancelacion = "23";
		} else if (situacaoBoleto.getCodigo().equals(10)) {
			motivoCancelacion = "10";
		} else {
			motivoCancelacion = "31, 32, 37, 23, 10";
		}

		if (situacaoBoleto.getCodigo().equals(1)) { // Somente Vendidos
			sql.append("SELECT ORIGINAL.BOLETO_ID, ");
			sql.append("       'VENDIDO' AS status, ");
			sql.append("       pv.NOMBPUNTOVENTA AS nomeAgenciaVenda, ");
			sql.append("       pe.NOMBPUNTOVENTA AS agencia, ");
			sql.append("       original.NUMFOLIOSISTEMA AS bilhete, ");
			sql.append("       original.CORRIDA_ID AS servico, ");
			sql.append("       original.NUMASIENTO AS poltrona, ");
			sql.append("       utilizado.MOTIVOCANCELACION_ID AS situacaoCancelado, ");
			sql.append("       UTILIZADO.FECCREACION AS dataEmissao, ");
			sql.append("       ORIGINAL.FECHORVIAJE AS dataEmbarque, ");
			sql.append("       ORIGINAL.MOTIVOCANCELACION_ID, ");
			sql.append("       ORIGINAL.PRECIOPAGADO AS preco, ");
			sql.append("       ORIGINAL.FECHORVENTA AS dataVenda, ");
			sql.append("       ORIGINAL.IMPORTEPEDAGIO + original.IMPORTESEGURO + original.IMPORTETAXAEMBARQUE + original.IMPORTEOUTROS AS taxas, ");
			sql.append("       r.DESCRUTA AS descricaoLinha, ");
			sql.append("       po.DESCPARADA AS descricaoOrigem, ");
			sql.append("       pd.DESCPARADA AS descricaoDestino ");
			sql.append("FROM BOLETO ORIGINAL ");
			sql.append("LEFT JOIN BOLETO UTILIZADO ON (original.boleto_id = UTILIZADO.boletooriginal_id AND utilizado.INDSTATUSBOLETO = 'E') ");
			sql.append("LEFT JOIN PUNTO_VENTA pv on(ORIGINAL.PUNTOVENTA_ID = pv.PUNTOVENTA_ID) ");
			sql.append("LEFT JOIN PUNTO_VENTA pe on(UTILIZADO.PUNTOVENTA_ID = pe.PUNTOVENTA_ID) ");
			sql.append("INNER JOIN RUTA r on(original.ruta_id = r.ruta_id) ");
			sql.append("INNER JOIN PARADA po ON (ORIGINAL.ORIGEN_ID = po.PARADA_ID) ");
			sql.append("INNER JOIN PARADA pd ON (ORIGINAL.DESTINO_ID = pd.PARADA_ID) ");
			sql.append("WHERE to_date(ORIGINAL.FECHORVENTA,'dd/MM/yy') BETWEEN :DATA_INICIAL AND :DATA_FINAL ");
			sql.append("  AND ORIGINAL.INDSTATUSBOLETO IN('V','T') ");
			sql.append("  AND ORIGINAL.TIPOVENTA_ID IN (5,12,18,41,49,81) ");
			sql.append(agencia.equals("-1") || agencia.equals("TODAS") ? "" : "  AND ORIGINAL.PUNTOVENTA_ID in (" + agencia + ") ");
			sql.append("AND ORIGINAL.EMPRESACORRIDA_ID =" + empresa.getEmpresaId() + " " );
		} else if (situacaoBoleto.getCodigo().equals(-1)) { // Todos (Vendidos e Cancelados)

			sql.append("SELECT ORIGINAL.BOLETO_ID, ");
			sql.append("       'VENDIDO' AS status, ");
			sql.append("       pv.NOMBPUNTOVENTA AS nomeAgenciaVenda, ");
			sql.append("       pe.NOMBPUNTOVENTA AS agencia, ");
			sql.append("       original.NUMFOLIOSISTEMA AS bilhete, ");
			sql.append("       original.CORRIDA_ID AS servico, ");
			sql.append("       original.NUMASIENTO AS poltrona, ");
			sql.append("       utilizado.MOTIVOCANCELACION_ID AS situacaoCancelado, ");
			sql.append("       UTILIZADO.FECCREACION AS dataEmissao, ");
			sql.append("       ORIGINAL.FECHORVIAJE AS dataEmbarque, ");
			sql.append("       ORIGINAL.MOTIVOCANCELACION_ID, ");
			sql.append("       ORIGINAL.PRECIOPAGADO AS preco, ");
			sql.append("       ORIGINAL.FECHORVENTA AS dataVenda, ");
			sql.append("       ORIGINAL.IMPORTEPEDAGIO + original.IMPORTESEGURO + original.IMPORTETAXAEMBARQUE + original.IMPORTEOUTROS AS taxas, ");
			sql.append("       r.DESCRUTA AS descricaoLinha, ");
			sql.append("       po.DESCPARADA AS descricaoOrigem, ");
			sql.append("       pd.DESCPARADA AS descricaoDestino ");
			sql.append("FROM BOLETO ORIGINAL ");
			sql.append("LEFT JOIN BOLETO UTILIZADO ON (original.boleto_id = UTILIZADO.boletooriginal_id AND utilizado.INDSTATUSBOLETO = 'E') ");
			sql.append("LEFT JOIN PUNTO_VENTA pv on(ORIGINAL.PUNTOVENTA_ID = pv.PUNTOVENTA_ID) ");
			sql.append("LEFT JOIN PUNTO_VENTA pe on(UTILIZADO.PUNTOVENTA_ID = pe.PUNTOVENTA_ID) ");
			sql.append("INNER JOIN RUTA r on(original.ruta_id = r.ruta_id) ");
			sql.append("INNER JOIN PARADA po ON (ORIGINAL.ORIGEN_ID = po.PARADA_ID) ");
			sql.append("INNER JOIN PARADA pd ON (ORIGINAL.DESTINO_ID = pd.PARADA_ID) ");
			sql.append("WHERE to_date(ORIGINAL.FECHORVENTA,'dd/MM/yy') BETWEEN :DATA_INICIAL AND :DATA_FINAL ");
			sql.append("  AND ORIGINAL.INDSTATUSBOLETO IN('V','T') ");
			sql.append("  AND ORIGINAL.TIPOVENTA_ID IN (5,12,18,41,49,81) ");
			sql.append(agencia.equals("-1") || agencia.equals("TODAS") ? "" : "  AND ORIGINAL.PUNTOVENTA_ID in (" + agencia + ") ");
			sql.append("AND ORIGINAL.EMPRESACORRIDA_ID =" + empresa.getEmpresaId() + " ");
			sql.append("UNION ALL ");
			sql.append("SELECT ORIGINAL.BOLETO_ID, ");
			sql.append("       'CANCELADO' AS status, ");
			sql.append("       pc.NOMBPUNTOVENTA AS nomeAgenciaVenda, ");
			sql.append("       pv.NOMBPUNTOVENTA AS agencia, ");
			sql.append("       ORIGINAL.NUMFOLIOSISTEMA AS bilhete, ");
			sql.append("       original.CORRIDA_ID AS servico, ");
			sql.append("       original.NUMASIENTO AS poltrona, ");
			sql.append("       ORIGINAL.MOTIVOCANCELACION_ID AS situacaoCancelado, ");
			sql.append("       ORIGINAL.FECHORVENTA AS dataEmissao, ");
			sql.append("       ORIGINAL.FECHORVIAJE AS dataEmbarque, ");
			sql.append("       ORIGINAL.MOTIVOCANCELACION_ID, ");
			sql.append("       ORIGINAL.PRECIOPAGADO AS preco, ");
			sql.append("       ORIGINAL.FECHORVENTA AS dataVenda, ");
			sql.append("       ORIGINAL.IMPORTEPEDAGIO + original.IMPORTESEGURO + original.IMPORTETAXAEMBARQUE + original.IMPORTEOUTROS AS taxas, ");
			sql.append("       r.DESCRUTA AS descricaoLinha, ");
			sql.append("       po.DESCPARADA AS descricaoOrigem, ");
			sql.append("       pd.DESCPARADA AS descricaoDestino ");
			sql.append("FROM BOLETO ORIGINAL ");
			sql.append("LEFT JOIN BOLETO UTILIZADO ON (ORIGINAL.BOLETOoriginal_ID = UTILIZADO.BOLETO_ID AND UTILIZADO.INDSTATUSBOLETO IN ('V','T')) ");
			sql.append("LEFT JOIN PUNTO_VENTA pv on(ORIGINAL.PUNTOVENTA_ID = pv.PUNTOVENTA_ID) ");
			sql.append("LEFT JOIN PUNTO_VENTA pc on(UTILIZADO.PUNTOVENTA_ID = pc.PUNTOVENTA_ID) ");
			sql.append("INNER JOIN RUTA r on(original.ruta_id = r.ruta_id) ");
			sql.append("INNER JOIN PARADA po ON (ORIGINAL.ORIGEN_ID = po.PARADA_ID) ");
			sql.append("INNER JOIN PARADA pd ON (ORIGINAL.DESTINO_ID = pd.PARADA_ID) ");
			sql.append("WHERE to_date(original.FECHORVENTA,'dd/MM/yy') BETWEEN :DATA_INICIAL AND :DATA_FINAL ");
			sql.append("  AND ORIGINAL.INDSTATUSBOLETO IN('C')  AND ORIGINAL.MOTIVOCANCELACION_ID in ("+motivoCancelacion+") ");
			sql.append("  AND ORIGINAL.TIPOVENTA_ID IN (5,12,18,41,49,81) ");
			sql.append(agencia.equals("-1") || agencia.equals("TODAS") ? "" : "  AND (utilizado.PUNTOVENTA_ID in (" + agencia + "))  AND ORIGINAL.MOTIVOCANCELACION_ID IN ( "+motivoCancelacion+") ");

			sql.append("AND ORIGINAL.EMPRESACORRIDA_ID =" + empresa.getEmpresaId() + " ");

		} else { // somente cancelados

			sql.append("SELECT ORIGINAL.BOLETO_ID, ");
			sql.append("       'CANCELADO' AS status, ");
			sql.append("       pc.NOMBPUNTOVENTA AS nomeAgenciaVenda, ");
			sql.append("       pv.NOMBPUNTOVENTA AS agencia, ");
			sql.append("       ORIGINAL.NUMFOLIOSISTEMA AS bilhete, ");
			sql.append("       original.CORRIDA_ID AS servico, ");
			sql.append("       original.NUMASIENTO AS poltrona, ");
			sql.append("       ORIGINAL.MOTIVOCANCELACION_ID AS situacaoCancelado, ");
			sql.append("       ORIGINAL.FECHORVENTA AS dataEmissao, ");
			sql.append("       ORIGINAL.FECHORVIAJE AS dataEmbarque, ");
			sql.append("       ORIGINAL.MOTIVOCANCELACION_ID, ");
			sql.append("       ORIGINAL.PRECIOBASE AS preco, ");
			sql.append("       ORIGINAL.FECHORVENTA AS dataVenda, ");
			sql.append("       ORIGINAL.IMPORTEPEDAGIO + original.IMPORTESEGURO + original.IMPORTETAXAEMBARQUE + original.IMPORTEOUTROS AS taxas, ");
			sql.append("       r.DESCRUTA AS descricaoLinha, ");
			sql.append("       po.DESCPARADA AS descricaoOrigem, ");
			sql.append("       pd.DESCPARADA AS descricaoDestino ");
			sql.append("FROM BOLETO ORIGINAL ");
			sql.append("LEFT JOIN BOLETO UTILIZADO ON (ORIGINAL.BOLETOoriginal_ID = UTILIZADO.BOLETO_ID AND UTILIZADO.INDSTATUSBOLETO IN ('V','T')) ");
			sql.append("LEFT JOIN PUNTO_VENTA pv on(ORIGINAL.PUNTOVENTA_ID = pv.PUNTOVENTA_ID) ");
			sql.append("LEFT JOIN PUNTO_VENTA pc on(UTILIZADO.PUNTOVENTA_ID = pc.PUNTOVENTA_ID) ");
			sql.append("INNER JOIN RUTA r on(original.ruta_id = r.ruta_id) ");
			sql.append("INNER JOIN PARADA po ON (ORIGINAL.ORIGEN_ID = po.PARADA_ID) ");
			sql.append("INNER JOIN PARADA pd ON (ORIGINAL.DESTINO_ID = pd.PARADA_ID) ");
			
			sql.append("WHERE to_date(original.FECHORVENTA,'dd/MM/yy') BETWEEN :DATA_INICIAL AND :DATA_FINAL ");
			sql.append("  AND ORIGINAL.INDSTATUSBOLETO IN('C') AND ORIGINAL.MOTIVOCANCELACION_ID in (" + motivoCancelacion + ")");
			sql.append("  AND ORIGINAL.TIPOVENTA_ID IN (5,12,18,41,49,81) ");
			sql.append(" AND ORIGINAL.EMPRESACORRIDA_ID =" + empresa.getEmpresaId() + " " );
			sql.append(agencia.equals("-1") || agencia.equals("TODAS") ? "" : "  AND (utilizado.PUNTOVENTA_ID in (" + agencia + ")) ");
		}

		return sql.toString();
	}

}
