package com.rjconsultores.ventaboletos.relatorios.impl;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
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 org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.rjconsultores.ventaboletos.relatorios.utilitarios.DataSource;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.Relatorio;
import com.rjconsultores.ventaboletos.relatorios.utilitarios.RelatorioDepositoBean;

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

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

	private List<RelatorioDepositoBean> lsDadosRelatorio;

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

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

					Connection conexao = this.relatorio.getConexao();

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

					Integer puntoventaId = parametros.get("puntoventaId") != null ? Integer.parseInt(parametros.get("puntoventaId").toString()) : null;
					Integer empresaId = parametros.get("empresaId") != null ? Integer.parseInt(parametros.get("empresaId").toString()) : null;
					Boolean filtrarPendentes = parametros.get("filtrarPendentes") != null ? Boolean.parseBoolean(parametros.get("filtrarPendentes").toString()) : false;
					String fecInicio = parametros.get("fecInicio").toString() + " 00:00:00";
					String fecFinal = parametros.get("fecFinal").toString() + " 23:59:59";

					String sql = getSQL(puntoventaId, empresaId, filtrarPendentes);

					PreparedStatement stmt = conexao.prepareStatement(sql);
					
					ResultSet rs = null;
					SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");

					stmt.setTimestamp(1, new java.sql.Timestamp(sdf.parse(fecInicio).getTime()));
					stmt.setTimestamp(2, new java.sql.Timestamp(sdf.parse(fecFinal).getTime()));
					
					rs = stmt.executeQuery();
					rs.setFetchSize(500);

					lsDadosRelatorio = new ArrayList<RelatorioDepositoBean>();

					while (rs.next()) {

						RelatorioDepositoBean deposito = new RelatorioDepositoBean();
						deposito.setNombempresa(rs.getString("nombempresa"));
						deposito.setNombpuntoventa(rs.getString("nombpuntoventa"));
						deposito.setNumpuntoventa(rs.getString("numpuntoventa"));
						deposito.setDtmotivo(rs.getDate("dtmotivo"));
						deposito.setSaldo(rs.getBigDecimal("saldo").multiply(BigDecimal.valueOf(-1)));
						deposito.setVrdeposito(rs.getBigDecimal("vrfechamento"));
						deposito.setVrfechamento(rs.getBigDecimal("vrdeposito"));
						deposito.setCodigoInstFinanceira(rs.getString("codinstfin"));
						deposito.setNomeInstFinanceira(rs.getString("nomeinstfin"));
						deposito.setFechamentocntcorrenteId(rs.getLong("fechamentocntcorrente_id"));
						
						if (! filtrarPendentes){
							deposito.setNumdeposito(rs.getString("numdeposito"));
						}

						lsDadosRelatorio.add(deposito);
					}
					
					addApenasPendentes(parametros, lsDadosRelatorio);
					
					if (lsDadosRelatorio.size() > 0) {
						setLsDadosRelatorio(lsDadosRelatorio);
					}
				}

			});
		} catch (Exception e) {
			log.error("", e);
		}
	}

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

	@Override
	protected void processaParametros() throws Exception {
	}

	private String getSQL(Integer puntoVentaId, Integer empresaId, boolean filtrarPendentes) {

		StringBuilder sql = new StringBuilder();
		
		sql.append(" SELECT DISTINCT tmp.nombempresa, ");
		sql.append("   tmp.nombpuntoventa, ");
		sql.append("   tmp.numpuntoventa, ");
		sql.append("   tmp.dtmotivo, ");
		sql.append("   tmp.saldo, ");
		sql.append("   tmp.vrfechamento, ");
		sql.append("   tmp.vrdeposito, ");

		if (! filtrarPendentes){
			sql.append("   tmp.numdeposito, ");
		} 

		sql.append("   tmp.codinstfin, ");
		sql.append("   tmp.nomeinstfin, ");
		sql.append("   tmp.fechamentocntcorrente_id ");
		sql.append(" FROM ");
		sql.append("   ( SELECT DISTINCT e.nombempresa, ");
		sql.append("     p.nombpuntoventa, ");
		sql.append("     p.numpuntoventa, ");
		sql.append("     f.fecfechamento                         AS dtmotivo, ");
		sql.append("     ( SUM(NVL(fd.valor_pago,0)) - f.total ) AS saldo, ");
		sql.append("     SUM(NVL(fd.valor_pago,0))               AS vrfechamento , ");
		sql.append("     f.total                                 AS vrdeposito, ");
		sql.append("     f.FECHAMENTOCNTCORRENTE_ID, ");

		if (! filtrarPendentes){
			sql.append("     fdp.NUMDEPOSITO as numdeposito, ");
		}

		sql.append("     ifin.CODIGO as codinstfin,  ");
		sql.append("     NVL(ifin.NOME,'') as nomeinstfin ");
		sql.append("   FROM fechamento_cntcorrente f ");
		sql.append("   LEFT JOIN punto_venta p ");
		sql.append("      ON p.puntoventa_id = f.puntoventa_id ");
		sql.append("   LEFT JOIN empresa e ");
		sql.append("      ON e.empresa_id = f.empresa_id ");
		sql.append("   LEFT JOIN fechamento_cct_deposito fd ");
		sql.append("      ON fd.fechamentocntcorrente_id = f.fechamentocntcorrente_id ");
		sql.append("      AND fd.activo = 1 ");
		sql.append("   LEFT JOIN FECHAMENTO_DEPOSITO fdp ");
		sql.append("      ON fdp.FECHAMENTODEPOSITO_ID = fd.FECHAMENTODEPOSITO_ID ");
		sql.append("      AND fdp.activo = 1 ");
//		sql.append("   LEFT JOIN FECHAMENTO_PARAMGERAL fp ");
//		sql.append("      ON e.EMPRESA_ID = fp.EMPRESA_ID ");
//		sql.append("      AND fp.activo = 1 ");
//		sql.append("   LEFT JOIN INSTI_FINANCEIRA ifin ");
//		sql.append("      ON ifin.CODIGO = fp.BOLETO_BANCO_COD  ");
//		sql.append("      AND ifin.activo = 1 ");
		sql.append("	LEFT JOIN INSTI_FINANCEIRA ifin ON ifin.INSTIFINANCEIRA_ID = fdp.INSTIFINANCEIRA_ID AND ifin.activo = 1 ");
		sql.append("   WHERE f.fecfechamento BETWEEN ? AND ? ");
		sql.append("     AND f.activo = 1 ");
		sql.append("     AND e.activo = 1 ");
		sql.append("     AND p.activo = 1 ");
		
		if (puntoVentaId != null && puntoVentaId != -1){
			sql.append(" and f.puntoventa_id = " + puntoVentaId);
		}
		if (empresaId != null && empresaId != -1){
			sql.append(" and e.empresa_id = " + empresaId);
		}
		sql.append(" GROUP BY e.nombempresa,  ");
		sql.append("   p.nombpuntoventa,  ");
		sql.append("   p.numpuntoventa,  ");
		sql.append("   f.fecfechamento,  ");
		sql.append("   f.FECHAMENTOCNTCORRENTE_ID,  ");
		sql.append("   f.total, ");

		if (!filtrarPendentes){
			sql.append("   fdp.NUMDEPOSITO, ");
		}
		
		sql.append("   ifin.CODIGO, ");
		sql.append("   ifin.NOME ) tmp ");
		
		if (filtrarPendentes){
			sql.append(" where ");
			sql.append(" tmp.saldo < tmp.vrdeposito and tmp.saldo <> 0 ");
		}
		sql.append(" ORDER BY tmp.nombempresa,  ");
		sql.append("   tmp.nomeinstfin, ");
		sql.append("   tmp.nombpuntoventa,  ");
		sql.append("   tmp.dtmotivo, ");
		sql.append("   tmp.vrdeposito  ");
		
		return sql.toString();
	}
	
	private void addApenasPendentes(Map<String, Object> parametros, List<RelatorioDepositoBean> lsDadosRelatorio) {
		Map<Long, BigDecimal> mapaValorDeposito = new HashMap<Long, BigDecimal>();
		Map<String, BigDecimal> mapaValorDepositoEmpresa = new HashMap<String, BigDecimal>();
		Map<Long, BigDecimal> mapaValorFechamento = new HashMap<Long, BigDecimal>();
		Map<String, BigDecimal> mapaValorFechamentoEmpresa = new HashMap<String, BigDecimal>();
		Iterator<RelatorioDepositoBean> iterator = lsDadosRelatorio.iterator();
		
		for (RelatorioDepositoBean bean: lsDadosRelatorio) {
			if (!mapaValorDeposito.containsKey(bean.getFechamentocntcorrenteId())) {
				mapaValorDeposito.put(bean.getFechamentocntcorrenteId(), bean.getVrdeposito());
			} else {
				mapaValorDeposito.put(bean.getFechamentocntcorrenteId(), mapaValorDeposito.get(bean.getFechamentocntcorrenteId()).add(bean.getVrdeposito()));
			}
			
			if (!mapaValorDepositoEmpresa.containsKey(bean.getNombempresa())) {
				mapaValorDepositoEmpresa.put(bean.getNombempresa(), bean.getVrdeposito());
			} else {
				mapaValorDepositoEmpresa.put(bean.getNombempresa(), mapaValorDepositoEmpresa.get(bean.getNombempresa()).add(bean.getVrdeposito()));
			}
			
			if (!mapaValorFechamento.containsKey(bean.getFechamentocntcorrenteId())) {
				mapaValorFechamento.put(bean.getFechamentocntcorrenteId(), bean.getVrfechamento());
			}

			if (!mapaValorFechamentoEmpresa.containsKey(bean.getNombempresa())) {
				mapaValorFechamentoEmpresa.put(bean.getNombempresa(), bean.getVrfechamento());
			} else {
				mapaValorFechamentoEmpresa.put(bean.getNombempresa(), mapaValorFechamentoEmpresa.get(bean.getNombempresa()).add(bean.getVrfechamento()));
			}
		}
		
		while (iterator.hasNext()) {
			RelatorioDepositoBean bean = iterator.next();
			BigDecimal deposito = mapaValorDeposito.get(bean.getFechamentocntcorrenteId());
			BigDecimal fechamento = mapaValorFechamento.get(bean.getFechamentocntcorrenteId());
			
			if (deposito.compareTo(fechamento) >= 0) {
				mapaValorDepositoEmpresa.put(bean.getNombempresa(), mapaValorDepositoEmpresa.get(bean.getNombempresa()).subtract(bean.getVrdeposito()));
				mapaValorFechamentoEmpresa.put(bean.getNombempresa(), mapaValorFechamentoEmpresa.get(bean.getNombempresa()).subtract(bean.getVrfechamento()));
				iterator.remove();
			}
		}
		
		BigDecimal totalDepositoGeral = BigDecimal.ZERO;
		BigDecimal totalFechamentoGeral = BigDecimal.ZERO;
		
		for (String nombempresa: mapaValorDepositoEmpresa.keySet()) {
			totalDepositoGeral = totalDepositoGeral.add(mapaValorDepositoEmpresa.get(nombempresa));
		}
		
		for (String nombempresa: mapaValorFechamentoEmpresa.keySet()) {
			totalFechamentoGeral = totalFechamentoGeral.add(mapaValorFechamentoEmpresa.get(nombempresa));
		}
		
		parametros.put("MAPA_VALOR_DEPOSITO_EMPRESA", mapaValorDepositoEmpresa);
		parametros.put("MAPA_VALOR_FECHAMENTO_EMPRESA", mapaValorFechamentoEmpresa);
		parametros.put("TOTAL_FECHAMENTO_GERAL", totalFechamentoGeral);
		parametros.put("TOTAL_PENDENTE_GERAL", totalFechamentoGeral.subtract(totalDepositoGeral));
	}
}
