package com.rjconsultores.ventaboletos.relatorios.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.rjconsultores.ventaboletos.entidad.Aidf;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.DataSource;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.Relatorio;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.RelatorioDocumentosFiscaisBean;
import com.rjconsultores.ventaboletos.web.utilerias.NamedParameterStatement;

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

public class RelatorioDocumentosFiscais extends Relatorio {

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

	private List<RelatorioDocumentosFiscaisBean> 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();

				Integer empresaId = (Integer) parametros.get("EMPRESA_ID");
				Integer estadoId = (Integer) parametros.get("ESTADO_ID");
				String agencia = (String) parametros.get("PUNTOVENTA");
				String tipoLinha = (String) parametros.get("TIPO_LINHA");
				Aidf aidf = (Aidf) parametros.get("AIDF");
				Boolean somenteCancelado = (Boolean) parametros.get("SOMENTE_CANCELADO");
				String especie = (String) parametros.get("ESPECIE");

				String sql = null;
				if (especie.equals("Bilhetes BPR")) {
					sql = getSqlBPR(empresaId, agencia, somenteCancelado, tipoLinha, aidf, estadoId);
				} else {
					sql = getSqlExcessoBagagem(empresaId, agencia, somenteCancelado, tipoLinha, aidf, estadoId);
				}

				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<RelatorioDocumentosFiscaisBean>();

				BigDecimal totalValorContabil = BigDecimal.ZERO;
				BigDecimal totalValorBaseCalculo = BigDecimal.ZERO;
				BigDecimal totalValorAliquiotaICMS = BigDecimal.ZERO;
				BigDecimal totalValorICMS = BigDecimal.ZERO;
				BigDecimal totalValorIsentas = BigDecimal.ZERO;
				BigDecimal totalValorOutras = BigDecimal.ZERO;
				BigDecimal totalValorCancelado = BigDecimal.ZERO;

				while (rset.next()) {

					RelatorioDocumentosFiscaisBean bean = new RelatorioDocumentosFiscaisBean();
					bean.setNumAIDF((String) (rset.getObject("numAIDF") == null ? "" : rset.getObject("numAIDF")));

					BigDecimal formInicial = (BigDecimal) rset.getObject("formInicial");
					bean.setFormInicial(formInicial.toString());

					BigDecimal formFinal = (BigDecimal) rset.getObject("formFinal");
					bean.setFormFinal(formFinal.toString());

					bean.setSerie((String) rset.getObject("serie"));
					bean.setSubSerie((String) rset.getObject("subSerie"));
					bean.setValorContabil((BigDecimal) rset.getObject("valorContabil"));
					bean.setValorBaseCalculo((BigDecimal) rset.getObject("valorBaseCalculo"));
					bean.setValorAliquiotaICMS((BigDecimal) rset.getObject("valorAliquiotaICMS"));
					bean.setValorICMS((BigDecimal) rset.getObject("valorICMS"));
					bean.setOutras((BigDecimal) rset.getObject("outras"));
					bean.setValorCancelado((BigDecimal) rset.getObject("valorCancelado"));
					bean.setNomeEstado((String) rset.getObject("nomeEstado"));
					bean.setIsentas((BigDecimal) rset.getObject("isentas"));

					lsDadosRelatorio.add(bean);
				}

				if (lsDadosRelatorio.size() > 0) {

					for (RelatorioDocumentosFiscaisBean bean : lsDadosRelatorio) {

						bean.setValorContabil(bean.getValorContabil().setScale(2, RoundingMode.HALF_EVEN));
						bean.setValorBaseCalculo(bean.getValorBaseCalculo().setScale(2, RoundingMode.HALF_EVEN));
						bean.setValorAliquiotaICMS(bean.getValorAliquiotaICMS().setScale(2, RoundingMode.HALF_EVEN));
						bean.setValorICMS(bean.getValorICMS().setScale(2, RoundingMode.HALF_EVEN));
						bean.setOutras(bean.getOutras().setScale(2, RoundingMode.HALF_EVEN));
						bean.setIsentas(bean.getIsentas().setScale(2, RoundingMode.HALF_EVEN));
						bean.setValorCancelado(bean.getValorCancelado().setScale(2, RoundingMode.HALF_EVEN));

						totalValorContabil = totalValorContabil.add(bean.getValorContabil() != null ? bean.getValorContabil() : BigDecimal.ZERO);
						totalValorBaseCalculo = totalValorBaseCalculo.add(bean.getValorBaseCalculo() != null ? bean.getValorBaseCalculo() : BigDecimal.ZERO);
						totalValorAliquiotaICMS = totalValorAliquiotaICMS.add(bean.getValorAliquiotaICMS() != null ? bean.getValorAliquiotaICMS() : BigDecimal.ZERO);
						totalValorICMS = totalValorICMS.add(bean.getValorICMS() != null ? bean.getValorICMS() : BigDecimal.ZERO);
						totalValorIsentas = totalValorIsentas.add(bean.getIsentas() != null ? bean.getIsentas() : BigDecimal.ZERO);
						totalValorOutras = totalValorOutras.add(bean.getOutras() != null ? bean.getOutras() : BigDecimal.ZERO);
						totalValorCancelado = totalValorCancelado.add(bean.getValorCancelado() != null ? bean.getValorCancelado() : BigDecimal.ZERO);
					}
					setLsDadosRelatorio(lsDadosRelatorio);

					parametros.put("TOTAL_VALOR_CONTABIL", totalValorContabil);
					parametros.put("TOTAL_VALOR_BASE_CALCULO", totalValorBaseCalculo);
					parametros.put("TOTAL_VALOR_ALIQUIOTA_ICMS", totalValorAliquiotaICMS);
					parametros.put("TOTAL_VALOR_ICMS", totalValorICMS);
					parametros.put("TOTAL_VALOR_ISENTAS", totalValorIsentas);
					parametros.put("TOTAL_VALOR_OUTRAS", totalValorOutras);
					parametros.put("TOTAL_VALOR_CANCELADO", totalValorCancelado);

				}

			}
		});

	}

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

	private String getSqlBPR(Integer empresaId, String agencia, Boolean somenteCancelado, String tipoLinha, Aidf aidf, Integer estadoId) {

		StringBuilder sql = new StringBuilder();
		sql.append("SELECT  ");
		sql.append("       coalesce(tabela.numAidf, '') AS numAidf, ");
		sql.append("       min(tabela.folio) AS formInicial, ");
		sql.append("       max(tabela.folio) AS formFinal, ");
		sql.append("       tabela.serie AS serie, ");
		sql.append("       tabela.subserie AS subSerie, ");
		sql.append("       tabela.nomeEstado AS nomeEstado, ");
		sql.append("       coalesce(sum(tabela.valorContabil),0) AS valorContabil, ");
		sql.append("       sum(valorBaseCalculo) AS valorBaseCalculo, ");
		sql.append("       tabela.valorAliquiotaICMS AS valorAliquiotaICMS, ");
		sql.append("       sum(tabela.valorICMS) AS valorICMS, ");
		sql.append("       sum(tabela.qntancelados) AS valorCancelado,  ");
		sql.append("       sum(tabela.outras) AS outras, ");
		sql.append("       sum(tabela.vlrisento) AS isentas ");
		sql.append("FROM ");
		sql.append("  (SELECT DISTINCT ");
		sql.append("          c.caja_id, ");
		sql.append("          a.docfiscal AS numAidf, ");
		sql.append("          to_number(c.numfoliopreimpreso) as folio, ");
		sql.append("          a.serie AS serie, ");
		sql.append("          a.subserie AS subserie, ");
		sql.append("          c.motivocancelacion_id AS motivoCancelacion, ");
		sql.append("          c.preciobase AS tarifa, ");
		sql.append("          ei.tributacaoimportacao AS valorAliquiotaICMS, ");
		sql.append("          CASE  WHEN c.MOTIVOCANCELACION_ID IS NOT NULL THEN 1 ELSE 0 END AS qntancelados, ");
		sql.append("          CASE  WHEN c.MOTIVOCANCELACION_ID IS NULL THEN c.PRECIOPAGADO    ELSE 0 END AS valorContabil, ");
		sql.append("          CASE  WHEN c.MOTIVOCANCELACION_ID IS NOT NULL THEN c.PRECIOPAGADO  ELSE 0 END AS valorCancelado, ");
		sql.append("          (coalesce(ei.PORCREDBASEICMS, 0) / 100.0) AS redBaseCalcIcms, ");
		sql.append("          CASE  WHEN c.MOTIVOCANCELACION_ID IS NULL THEN c.PRECIOPAGADO - (c.PRECIOPAGADO * (coalesce(ei.PORCREDBASEICMS, 0) / 100.0) ) ELSE 0  END AS valorBaseCalculo, ");
		sql.append("          CASE  WHEN c.MOTIVOCANCELACION_ID IS NULL THEN ((c.PRECIOPAGADO - (c.PRECIOPAGADO * (coalesce(ei.PORCREDBASEICMS, 0) / 100.0) )) * ei.TRIBUTACAOIMPORTACAO) / 100 ELSE 0  END AS valorICMS, ");
		sql.append("          CASE  WHEN c.MOTIVOCANCELACION_ID IS NULL THEN c.PRECIOPAGADO - (c.PRECIOPAGADO - (c.PRECIOPAGADO * (coalesce(ei.PORCREDBASEICMS, 0) / 100.0) )) ELSE 0 END AS outras, ");
		sql.append("          eai.estado_id AS estadoId, ");
		sql.append("          eai.NOMBESTADO AS nomeEstado, ");
		sql.append("          coalesce(pos.DESCPARADA, po.DESCPARADA) AS origem, ");
		sql.append("          coalesce(pds.DESCPARADA, pd.DESCPARADA) AS destino, ");
		sql.append("          CASE WHEN((coalesce(eai.cveestado, eos.cveestado, eo.cveestado)) = (coalesce(eds.cveestado, ed.cveestado))) THEN 0  ELSE 1 END AS isInterEstadual, ");
		sql.append("          COALESCE((IMPORTETAXAEMBARQUE + IMPORTEPEDAGIO + IMPORTESEGURO),0) AS vlrisento ");
		sql.append("   FROM caja c ");
		sql.append("   INNER JOIN aidf a ON a.aidf_id = c.aidf_id ");
		sql.append("   LEFT JOIN estado eai ON a.estado_id = eai.estado_id ");
		sql.append("   JOIN marca m ON c.marca_id = m.marca_id ");
		sql.append("   JOIN empresa e ON e.empresa_id = m.empresa_id ");
		sql.append("   JOIN parada po ON po.parada_id = c.origen_id ");
		sql.append("   JOIN ciudad co ON co.ciudad_id = po.ciudad_id ");
		sql.append("   JOIN estado eo ON eo.estado_id = co.estado_id ");
		sql.append("   JOIN parada pd ON pd.parada_id = c.destino_id ");
		sql.append("   JOIN ciudad cd ON cd.ciudad_id = pd.ciudad_id ");
		sql.append("   JOIN estado ed ON ed.estado_id = cd.estado_id ");
		sql.append("   LEFT JOIN alias_servico s ON s.origen_id = c.origen_id  AND s.destino_id = c.destino_id ");
		sql.append("        AND (s.corrida_id = c.corrida_id OR s.corrida_id IS NULL) AND s.ruta_id = c.ruta_id AND s.activo = 1 ");
		sql.append("   LEFT JOIN parada pos ON pos.parada_id = s.aliasorigen_id ");
		sql.append("   LEFT JOIN ciudad cos ON cos.ciudad_id = pos.ciudad_id ");
		sql.append("   LEFT JOIN estado eos ON eos.estado_id = cos.estado_id ");
		sql.append("   LEFT JOIN parada pds ON pds.parada_id = s.aliasdestino_id ");
		sql.append("   LEFT JOIN ciudad cds ON cds.ciudad_id = pds.ciudad_id ");
		sql.append("   LEFT JOIN estado eds ON eds.estado_id = cds.estado_id ");
		sql.append("   INNER JOIN empresa_imposto ei ON ei.empresa_id = e.empresa_id ");
		sql.append("            and ei.estado_id = eai.estado_id and ei.activo = 1 ");
		sql.append("     WHERE c.feccreacion between :DATA_INICIAL and :DATA_FINAL ");
		sql.append("           AND e.empresa_id = " + empresaId + " ");
		sql.append("           AND a.aidfesp_id  = 1 ");
		sql.append(somenteCancelado == true ? " AND c.indcancelacion = 1 " : " ");
		sql.append(aidf != null ? " AND a.aidf_id = " + aidf.getAidfId() + " " : " ");
		sql.append(estadoId != null && !isEstadoTodos(estadoId) ? " AND eai.estado_id IN (" + estadoId + ") " : " ");
		sql.append("   ORDER BY a.ACFISCAL, to_number(c.numfoliopreimpreso) ");
		sql.append("    ) tabela ");
		sql.append(tipoLinha.equals(" INTERMUNICIPAL") ? " where tabela.isInterEstadual = 1 " : tipoLinha.equals("INTERESTADUAL") ? " where tabela.isInterEstadual = 0 " : " ");
		sql.append(" GROUP BY tabela.numAidf, ");
		sql.append("         tabela.serie, ");
		sql.append("         tabela.subserie, ");
		sql.append("         tabela.nomeEstado, ");
		sql.append("         tabela.valorAliquiotaICMS ");
		sql.append(" ORDER BY tabela.numAidf, tabela.nomeEstado ");

		return sql.toString();
	}

	private String getSqlExcessoBagagem(Integer empresaId, String agencia, Boolean somenteCancelado, String tipoLinha, Aidf aidf, Integer estadoId) {

		StringBuilder sql = new StringBuilder();
		sql.append("SELECT tabela.docfiscal AS numAidf, ");
		sql.append("       to_number(tabela.forminicial) AS formInicial, ");
		sql.append("       to_number(tabela.formfinal) AS formFinal, ");
		sql.append("       tabela.serie AS serie, ");
		sql.append("       tabela.subserie AS subSerie, ");
		sql.append("       tabela.nomeEstado AS nomeEstado, ");
		sql.append("       coalesce(sum(tabela.valorContabil),0) AS valorContabil, ");
		sql.append("       sum(valorBaseCalculo) AS valorBaseCalculo, ");
		sql.append("       tabela.valorAliquiotaICMS AS valorAliquiotaICMS, ");
		sql.append("       sum(tabela.valorICMS) AS valorICMS, ");
		sql.append("       coalesce(sum(tabela.qntancelados),0) AS valorCancelado, ");
		sql.append("       sum(tabela.outras) AS outras, ");
		sql.append("       sum(tabela.vlrisento) AS isentas ");
		sql.append("FROM ");
		sql.append("  (SELECT DISTINCT ");
		sql.append("          a.docfiscal, ");
		sql.append("          aidf.forminicial, ");
		sql.append("          aidf.formfinal, ");
		sql.append("          coalesce(cdv.NUMSERIEPREIMPRESA, 'X') AS numAidf, ");
		sql.append("          aidf.serie AS serie, ");
		sql.append("          aidf.subserie AS subserie, ");
		sql.append("          coalesce(cdv.NUMFOLIOPREIMPRESO, '0') AS folio, ");
		sql.append("          case when cdv.precio < 0 then 31 else null end AS motivoCancelacion, ");
		sql.append("          cdv.precio AS tarifa, ");
		sql.append("          cdv.precio as valor, ");
		sql.append("          CASE  WHEN cdv.precio < 0 THEN 1 ELSE 0 END AS qntancelados, ");
		sql.append("          ed.tributacaoimportacao AS valorAliquiotaICMS, ");
		sql.append("          CASE  WHEN cdv.precio >= 0 THEN cdv.precio ELSE 0 END AS valorContabil, ");
		sql.append("          CASE  WHEN cdv.precio < 0 THEN cdv.precio ELSE 0 END AS valorCancelado, ");
		sql.append("          COALESCE(ed.PORCREDBASEICMS / 100,0) AS redBaseCalcIcms, ");
		sql.append("          CASE  WHEN cdv.precio >= 0 THEN cdv.precio - (cdv.precio * COALESCE(ed.PORCREDBASEICMS / 100,0)) ELSE 0  END AS valorBaseCalculo, ");
		sql.append("          CASE  WHEN cdv.precio >= 0 THEN ((cdv.precio * ((ed.TRIBUTACAOIMPORTACAO - (COALESCE(ed.PORCREDBASEICMS * ed.TRIBUTACAOIMPORTACAO /100,0))))) / 100) ELSE 0  END AS valorICMS, ");
		sql.append("          CASE  WHEN cdv.precio >= 0 THEN cdv.precio - (cdv.precio - (cdv.precio * COALESCE(ed.PORCREDBASEICMS / 100,0))) ELSE 0 END AS outras, ");
		sql.append("          eai.estado_id AS estadoId, ");
		sql.append("          eai.NOMBESTADO AS nomeEstado, ");
		sql.append("          '' AS origem, ");
		sql.append("          '' AS destino, ");
		sql.append("          0 AS isInterEstadual, ");
		sql.append("          0 AS vlrisento ");
		sql.append("from evento_extra ee ");
		sql.append("  join caja_diversos cdv on cdv.eventoextra_id = ee.eventoextra_id ");
		sql.append("  join aidf aidf on aidf.serie = cdv.numseriepreimpresa and cdv.numfoliopreimpreso between aidf.forminicial and aidf.formfinal ");
		sql.append("  left join estado eai ON aidf.estado_id = eai.estado_id ");
		sql.append("  join punto_venta pv on pv.puntoventa_id = cdv.puntoventa_id ");
		sql.append("  join parada pp on pp.parada_id = pv.parada_id ");
		sql.append("  join ciudad cc on cc.ciudad_id = pp.ciudad_id ");
		sql.append("  join estado es on es.estado_id = cc.estado_id ");
		sql.append("  join empresa_imposto ed ON ed.empresa_id = ee.empresa_id and ed.estado_id = coalesce(aidf.estado_id, es.estado_id) and ed.activo = 1 ");
		sql.append("where ee.tipoeventoextra_id in (1,81,82) ");
		sql.append("  and ee.fechoringreso between :DATA_INICIAL and :DATA_FINAL ");
		sql.append("  and aidf.aidfesp_id  = 2 ");
		sql.append("  and ee.empresa_id = " + empresaId + " ");
		sql.append(estadoId != null && !isEstadoTodos(estadoId) ? "  and eai.estado_id IN (" + estadoId + ") " : "");
		sql.append(aidf != null ? " and aidf.aidf_id = " + aidf.getAidfId() + " " : " ");
		// sql.append(somenteCancelado == true ? " AND c.INDCANCELACION = 1" : " ");
		sql.append("    )tabela ");
		// sql.append(tipoLinha.equals("INTERMUNICIPAL") ? " where tabela.isInterEstadual = 1" : tipoLinha.equals("INTERESTADUAL") ? " where tabela.isInterEstadual = 0" : " ");
		sql.append("GROUP BY tabela.numAidf,  ");
		sql.append("         tabela.serie, ");
		sql.append("         tabela.subSerie, ");
		sql.append("         tabela.nomeEstado, ");
		sql.append("         tabela.valorAliquiotaICMS, ");
		sql.append("         tabela.docfiscal, ");
		sql.append("         tabela.forminicial, ");
		sql.append("         tabela.formfinal ");
		sql.append("ORDER BY tabela.nomeEstado, tabela.numAidf ");

		return sql.toString();
	}

	private boolean isEstadoTodos(Integer estadoId) {
		if (estadoId == -1 || estadoId == null)
			return true;
		else
			return false;
	}
}
