package com.rjconsultores.ventaboletos.utilerias.exportacaofiscal.vo;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.rjconsultores.ventaboletos.utilerias.MoneyHelper;

public class ExportacaoBPR {
	private static final String CODIGO_INDICADOR_CONTR_PREVIDENCIARIA = "00000060";
	
	private List<ExportacaoBPRBase> listaRegistroBPR;
	
	private List<ExportacaoRMDTipoPAR> listaRegistroBPRTipoPAR;
	private List<ExportacaoRMDTipoRMD> listaRegistroBPRTipoRMD;
	private List<ExportacaoRMDTipoSeqBPS> listaRegistroBPRTipoSeqBPS;
	
	public ExportacaoBPR() {
		listaRegistroBPR = new ArrayList<ExportacaoBPRBase>(0);
		
		listaRegistroBPRTipoPAR = new ArrayList<ExportacaoRMDTipoPAR>(0);
		listaRegistroBPRTipoRMD = new ArrayList<ExportacaoRMDTipoRMD>(0);
		listaRegistroBPRTipoSeqBPS = new ArrayList<ExportacaoRMDTipoSeqBPS>(0);
	}

	public List<ExportacaoBPRBase> getListaRegistroBPR() {
		return listaRegistroBPR;
	}

	public List<ExportacaoRMDTipoPAR> getListaRegistroBPRTipoPAR() {
		return listaRegistroBPRTipoPAR;
	}

	public List<ExportacaoRMDTipoRMD> getListaRegistroBPRTipoRMD() {
		return listaRegistroBPRTipoRMD;
	}

	public List<ExportacaoRMDTipoSeqBPS> getListaRegistroBPRTipoSeqBPS() {
		return listaRegistroBPRTipoSeqBPS;
	}
	
	public void gerarListas() {
		ordenarLista();
		
		gerarPAR();
		gerarRMD();
		gerarBPS_DBP();
	}

	private void ordenarLista() {
		Collections.sort(listaRegistroBPR, new Comparator<ExportacaoBPRBase>(){
		    public int compare(ExportacaoBPRBase e1, ExportacaoBPRBase e2) {
		        String c1 = e1.getDataEmissao() + "-" + e1.getNumeroFormulario() + "-" + e1.getCfop() + "-" + e1.getUfDestino();
		        String c2 = e2.getDataEmissao() + "-" + e2.getNumeroFormulario() + "-" + e2.getCfop() + "-" + e2.getUfDestino();
		    	
		    	return c1.compareToIgnoreCase(c2);
		    }
		});
	}

	private void gerarPAR() {
		listaRegistroBPRTipoPAR.clear();
		
		ExportacaoRMDTipoPAR registro = null;
		
		Map<String, ExportacaoRMDTipoPAR> group = new HashMap<String, ExportacaoRMDTipoPAR>(0); 
		
		for (ExportacaoBPRBase base : listaRegistroBPR) {
			String key = base.getCodigoEstabelecimentoPar() + "-" + base.getCodigoEstabelecimentoPar() + "-" + base.getNomeParticipante();
			
			if (group.containsKey(key)) {
				continue;
			}
			
			registro = new ExportacaoRMDTipoPAR();
			registro.setCodigoParticipante(base.getCodigoParticipantePar());
			registro.setCodigoEstabelecimento(base.getCodigoEstabelecimentoPar());
			registro.setNomeParticipante(base.getNomeParticipante());
			registro.setUfParticipante(base.getUfParticipante());
			registro.setCpfParticipante(base.getCpfParticipante());
			registro.setIeParticipante(base.getIeParticipante());
			registro.setLogradouro(base.getLogradouro());
			registro.setNumero(base.getNumero());
			registro.setComplemento(base.getComplemento());
			registro.setBairro(base.getBairro());
			registro.setCep(base.getCep());
			
			group.put(key, registro);
		}
		
		for (Map.Entry<String, ExportacaoRMDTipoPAR> entry : group.entrySet()) {
			listaRegistroBPRTipoPAR.add(entry.getValue());
		}
		
		Collections.sort(listaRegistroBPRTipoPAR, new Comparator<ExportacaoRMDTipoPAR>(){
		    public int compare(ExportacaoRMDTipoPAR e1, ExportacaoRMDTipoPAR e2) {
		        String c1 = e1.getCodigoParticipante() + "-" + e1.getCodigoEstabelecimento() + "-" + e1.getNomeParticipante();
		        String c2 = e2.getCodigoParticipante() + "-" + e2.getCodigoEstabelecimento() + "-" + e2.getNomeParticipante();
		    	
		    	return c1.compareToIgnoreCase(c2);
		    }
		});
	}

	private void gerarRMD() {
		listaRegistroBPRTipoRMD.clear();
		
		ExportacaoRMDTipoRMD registro = null;
		
		Map<String, ExportacaoRMDTipoRMD> group = new HashMap<String, ExportacaoRMDTipoRMD>(0); 
		
		for (ExportacaoBPRBase base : listaRegistroBPR) {

			// String numeroAIDF = base.getNumeroAIDF();
			// if (numeroAIDF == null || numeroAIDF.trim().isEmpty() || numeroAIDF.trim().equals("0")) {
			// continue;
			// }

			String key = base.getCodigoEstabelecimento() + "-" + base.getNumeroAIDFRMD() + "-" + base.getNumeroFormularioBilheteAIDF();
			
			if (group.containsKey(key)) {
				continue;
			}
			
			registro = new ExportacaoRMDTipoRMD();
			registro.setDataEmissao(base.getDataEmissaoRMD());
			registro.setCodigoParticipante(base.getDocumentoCancelado() ? base.getCodigoParticipantePar() : base.getCodigoParticipante());
			registro.setCodigoEstabelecimento( base.getDocumentoCancelado() ? base.getCodigoEstabelecimentoPar() :  base.getCodigoEstabelecimento());
			registro.setNumeroAIDF(base.getNumeroAIDFRMD());
			registro.setSerieAIDF(base.getSerieAIDFRMD());
			registro.setSubSerieAIDF(base.getSubSerieAIDFRMD());
			registro.setNumeroBilheteAIDF(base.getNumeroFormularioBilheteAIDF());
			registro.setNumeroFormularioAIDF(base.getNumeroFormularioBilheteAIDF());
			registro.setCancelado(base.getDocumentoCancelado());
			registro.setCodigoContabil(base.getCodigoContabil());
			
			group.put(key, registro);
		}
		
		for (Map.Entry<String, ExportacaoRMDTipoRMD> entry : group.entrySet()) {
			listaRegistroBPRTipoRMD.add(entry.getValue());
		}
		
		Collections.sort(listaRegistroBPRTipoRMD, new Comparator<ExportacaoRMDTipoRMD>(){
		    public int compare(ExportacaoRMDTipoRMD e1, ExportacaoRMDTipoRMD e2) {
		        String c1 = e1.getCodigoEstabelecimento() + "-" + e1.getNumeroAIDF() + "-" + e1.getNumeroBilheteAIDF();
		        String c2 = e2.getCodigoEstabelecimento() + "-" + e2.getNumeroAIDF() + "-" + e2.getNumeroBilheteAIDF();
		    	
		    	return c1.compareToIgnoreCase(c2);
		    }
		});
	}

	private void gerarBPS_DBP() {
		listaRegistroBPRTipoSeqBPS.clear();

		ExportacaoRMDTipoSeqBPS registroBPS = null;
		ExportacaoRMDTipoSeqDBP registroDBP = null;

		Long numeroInicial = 0l;
		Long numeroFinal = 0l;

		String dataEmissaoControle = "";
		Integer cfopControle = 0;

		Integer quantidadeTotal = 0;
		Integer quantidadeCancelado = 0;

		BigDecimal totalizador = BigDecimal.ZERO;
		
		for (ExportacaoBPRBase base : listaRegistroBPR) {
			Integer codigoEstabelecimento = base.getCodigoEstabelecimento();
			String numeroAIDF = base.getNumeroAIDF();
			String serieAIDF = base.getSerieAIDF();
			String subSerieAIDF = base.getSubSerieAIDF();
			String numeroAIDFRMD = base.getNumeroAIDFRMD();
			String serieAIDFRMD = base.getSerieAIDFRMD();
			String subSerieAIDFRMD = base.getSubSerieAIDFRMD();
			Integer numeroRMD = base.getNumeroRMD();
			String dataEmissao =  base.getDataEmissao();
			Long numeroFormulario = base.getNumeroFormulario();
			String ufDestino = base.getUfDestino();
			Integer cfop = base.getCfop();
			String ufOrigem = base.getUfOrigem();
			Integer municipioOrigem = base.getMunicipioOrigem();
			Boolean isenta = (base.getBoletoIsento() == 1);
			Boolean cancelado = (base.getBoletoCancelado() == 1);
			BigDecimal valorTotal = base.getValorPago();
			BigDecimal red_base_calc_icms = base.getReducaoBaseCalcICMS();
			BigDecimal porc_red_municipal = base.getPorcReducaoMunicipal();
			BigDecimal porc_red_estadual = base.getPorcReducaoEstadual();
			BigDecimal tributacao_importacao = base.getTributacaoImportacao();
			
			if (base.getDocumentoCancelado())
				continue;

			if (numeroAIDF == null || numeroAIDF.trim().isEmpty() || numeroAIDF.trim().equals("0")) {
				continue;
			}
			
			// BPR
			if ((numeroFinal + 1) != numeroFormulario || !dataEmissaoControle.equals(dataEmissao) || !cfopControle.equals(cfop)) {
				numeroInicial = numeroFormulario;
				dataEmissaoControle = dataEmissao;
				cfopControle = cfop;

				registroBPS = new ExportacaoRMDTipoSeqBPS();
				registroBPS.setEspecie("BPR");
				registroBPS.setNumeroInicial(numeroInicial);
				registroBPS.setCodigoEstabelecimento(codigoEstabelecimento);
				registroBPS.setNumeroAIDF(numeroAIDF);
				registroBPS.setSerieAIDF(serieAIDF);
				registroBPS.setSubSerieAIDF(subSerieAIDF);
				registroBPS.setNumeroAIDFRMD(numeroAIDFRMD);
				registroBPS.setSerieAIDFRMD(serieAIDFRMD);
				registroBPS.setSubSerieAIDFRMD(subSerieAIDFRMD);
				registroBPS.setNumeroRMD(numeroRMD);
				registroBPS.setDataEmissao(dataEmissao);
				registroBPS.setInfoPadraoBilhetePassagem(CODIGO_INDICADOR_CONTR_PREVIDENCIARIA);

				listaRegistroBPRTipoSeqBPS.add(registroBPS);

				quantidadeTotal = 0;
				quantidadeCancelado = 0;

				totalizador = BigDecimal.ZERO;
			}

			quantidadeTotal++;

			if (cancelado) {
				quantidadeCancelado++;
			} else {
				totalizador = MoneyHelper.somar(totalizador, valorTotal);
			}

			numeroFinal = numeroFormulario;

			registroBPS.setNumeroFinal(numeroFinal);

			registroBPS.setQuantidadeTotal(quantidadeTotal);
			registroBPS.setQuantidadeCancelados(quantidadeCancelado);
			registroBPS.setValorTotal(totalizador);

			// DBP
			registroDBP = new ExportacaoRMDTipoSeqDBP(ufDestino);

			Integer indice = registroBPS.getListaDBP().indexOf(registroDBP);

			if (indice == -1) {
				registroBPS.getListaDBP().add(registroDBP);

				registroDBP.setCfop(cfop); // IM=5357; serviço IE= 6357
				registroDBP.setUfOrigem(ufOrigem);
				registroDBP.setMunicipioOrigem(municipioOrigem);

				registroDBP.setCodigoSituacaoTribColunaB(null);

				// 00 - tributação normal; 20 - tributação com redução na base de calculo; 40 - isentos
				if (isenta) {
					registroDBP.setCodigoSituacaoTribColunaB(40);
				}

				// 00 - tributação normal; 20 - tributação com redução na base de calculo; 40 - isentos
				if (registroDBP.getCodigoSituacaoTribColunaB() == null) {
					registroDBP.setCodigoSituacaoTribColunaB(red_base_calc_icms == null || red_base_calc_icms.compareTo(BigDecimal.ZERO) == 0 ? 0 : 20);
				}

				registroDBP.setValorBaseCalculoICMS(BigDecimal.ZERO);
				registroDBP.setValorTotal(BigDecimal.ZERO);
				registroDBP.setValorICMS(BigDecimal.ZERO);
				registroDBP.setValorICMSIsento(BigDecimal.ZERO);
				registroDBP.setValorICMSOutros(BigDecimal.ZERO);
			} else {
				registroDBP = registroBPS.getListaDBP().get(indice);
			}

			BigDecimal valorBaseCalculoICMS = BigDecimal.ZERO;

			BigDecimal valorIsenta = BigDecimal.ZERO;
			BigDecimal valorIsentaOutros = BigDecimal.ZERO;

			if (base.getBoletoIsento() == 1) {
				valorIsenta = valorTotal;
				valorTotal = BigDecimal.ZERO;
			} else {
				if (red_base_calc_icms != null) {
					valorBaseCalculoICMS = valorTotal.subtract(valorTotal.multiply(red_base_calc_icms.divide(BigDecimal.valueOf(100d))));
				} else {
					valorBaseCalculoICMS = valorTotal;
				}
			}

			registroDBP.setAliquotaICMS(tributacao_importacao);

			if (tributacao_importacao == null) {
				tributacao_importacao = BigDecimal.ZERO;
			} else {
				if (red_base_calc_icms != null) {
					BigDecimal porc_red = BigDecimal.ZERO;

					if (ufOrigem.equals(ufDestino)) {
						if (porc_red_municipal != null) {
							porc_red = porc_red_municipal;
						}
					} else {
						if (porc_red_estadual != null) {
							porc_red = porc_red_estadual;
						}
					}

					BigDecimal porc = tributacao_importacao.subtract(porc_red.divide(BigDecimal.valueOf(100d)));
					valorIsentaOutros = valorTotal.multiply(porc);
				}

				tributacao_importacao = MoneyHelper.dividir(tributacao_importacao, BigDecimal.valueOf(100d));
			}

			BigDecimal valorICMS = MoneyHelper.multiplicar(valorBaseCalculoICMS, tributacao_importacao);

			registroDBP.setValorBaseCalculoICMS(registroDBP.getValorBaseCalculoICMS().add(valorBaseCalculoICMS));
			registroDBP.setValorTotal(registroDBP.getValorTotal().add(valorTotal));
			registroDBP.setValorICMS(registroDBP.getValorICMS().add(valorICMS));
			registroDBP.setValorICMSIsento(registroDBP.getValorICMSIsento().add(valorIsenta));
			registroDBP.setValorICMSOutros(registroDBP.getValorICMSOutros().add(valorIsentaOutros));
		}
		
		Collections.sort(listaRegistroBPRTipoSeqBPS, new Comparator<ExportacaoRMDTipoSeqBPS>(){
		    public int compare(ExportacaoRMDTipoSeqBPS e1, ExportacaoRMDTipoSeqBPS e2) {
		        String c1 = e1.getDataEmissao();
		        String c2 = e2.getDataEmissao();
		    	
		    	return c1.compareToIgnoreCase(c2);
		    }
		});
	}
}
