package com.rjconsultores.ventaboletos.utilerias.archivointegracion;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.rjconsultores.ventaboletos.constantes.Constantes;
import com.rjconsultores.ventaboletos.entidad.Empresa;
import com.rjconsultores.ventaboletos.utilerias.DateUtil;
import com.rjconsultores.ventaboletos.utilerias.StringHelper;
import com.rjconsultores.ventaboletos.utilerias.UtiliteriasFiscal;
import com.rjconsultores.ventaboletos.vo.impressaofiscal.ImportacionFiscalVO;
import com.rjconsultores.ventaboletos.vo.impressaofiscal.ItemFiscalVO;
import com.rjconsultores.ventaboletos.vo.impressaofiscal.SiglaMotivoCancelacion;
import com.rjconsultores.ventaboletos.vo.impressaofiscal.SituacaoTributaria;

public class ArchivoIntegracionECF {

	private static final Logger log = LogManager.getLogger(ArchivoIntegracionECF.class);

	public File importacionFiscalECFGenerico(Date inicio, Date fim, Empresa empresa, boolean isNormal, boolean isCancelados, boolean isPendencias, List<ImportacionFiscalVO> list) {

		try {
			String nomeArquivo = "fiscal_ecf_" + DateUtil.getStringDate(Calendar.getInstance().getTime(), "yyyyMMddhhmmss");
			if (isCancelados) {
				nomeArquivo = "fiscal_ecf_cancel_" + DateUtil.getStringDate(Calendar.getInstance().getTime(), "yyyyMMddhhmmss");
			} else if (isPendencias) {
				nomeArquivo = "fiscal_ecf_pendencias_" + DateUtil.getStringDate(Calendar.getInstance().getTime(), "yyyyMMddhhmmss");
			}

			File arquivo = File.createTempFile(nomeArquivo, ".txt");

			PrintWriter gravarArq = new PrintWriter(new OutputStreamWriter(new FileOutputStream(arquivo), Constantes.UTF_8));

			Integer seq = 1;

			String cnpjFilial = empresa.getCnpj();
			String brancos371 = StringHelper.preencherStringEspacoEsquerda(null, 371);
			String dataAgora = DateUtil.getStringDate(Calendar.getInstance().getTime(), UtiliteriasFiscal.DATE_FORMAT_FISCAL);
			String seqAbertura = StringHelper.preencherZeroEsquerda(seq.toString(), 6);

			String abertura = UtiliteriasFiscal.aberturaDeArquivo("0", dataAgora, cnpjFilial, brancos371, seqAbertura);
			gravarArq.print(abertura + UtiliteriasFiscal.QUEBRA_LINHA);

			Integer qtdDoc = 0;
			Integer qtdItens = 0;

			String header = null;
			List<String> itensDocs = new ArrayList<String>();

			for (ImportacionFiscalVO item : list) {

				qtdDoc++;
				header = null;
				itensDocs = new ArrayList<String>();

				String data = item.getDataEmissao();
				String brancos = StringHelper.preencherStringEspacoEsquerda(null, 202);
				String cnpjEcf = item.getCnpjEcf() == null ? cnpjFilial : item.getCnpjEcf();

				String serie = item.getNumImpressora();
				if (serie.length() >= 20) {
					serie = serie.substring(17);
					serie = StringHelper.preencherStringEspacoEsquerda(serie, 3);
				} else {
					serie = StringHelper.preencherStringEspacoEsquerda(null, 3);
				}

				String especie = StringHelper.preencherStringEspacoDireita("CF", 5);

				String codigoCliente = StringHelper.preencherStringEsquerda(null, 6, "9");
				String filialCliente = StringHelper.preencherStringEsquerda(null, 2, "9");
				String condicaoPagamento = StringHelper.preencherStringEsquerda(null, 3, "9");

				String valorPIS = StringHelper.preencherZeroEsquerda("", 14);
				String valorCofins = StringHelper.preencherZeroEsquerda("", 14);
				String valorCSLL = StringHelper.preencherZeroEsquerda("", 14);

				String coo = StringHelper.preencherStringEspacoDireita(item.getCoo(), 9);

				BigDecimal valorTotal = UtiliteriasFiscal.arredondar(UtiliteriasFiscal.valorTotalItensECF(item));
				String valorTotalDocumanto = UtiliteriasFiscal.formataEspacosDecimalDireita(valorTotal, 14);
				String valorItens = valorTotalDocumanto;

				HashMap<String, String> aliquotaBaseCalculo = getAliquotaBaseCalculo(item);
				String aliquota = aliquotaBaseCalculo.get("aliquota");
				String imposto = aliquotaBaseCalculo.get("imposto");
				String totalICMSIsento = aliquotaBaseCalculo.get("totalICMSIsento");
				String totalICMSNaotributado = aliquotaBaseCalculo.get("totalICMSNaotributado");

				String origenUf = StringHelper.preencherStringEspacoEsquerda(item.getOrigenUf(), 2);
				String origen = item.getOrigenId() == null ? StringUtils.EMPTY : item.getOrigenId().toString();
				if (origen.length() > 2) {
					origen = origen.substring(2);
					origen = StringHelper.preencherStringEspacoEsquerda(origen, 5);
				} else {
					origen = StringHelper.preencherStringEspacoEsquerda(origen, 5);
				}

				String destinoUf = StringHelper.preencherStringEspacoEsquerda(item.getDestinoUf(), 2);
				String destino = item.getDestinoId() == null ? StringUtils.EMPTY : item.getDestinoId().toString();
				if (destino.length() > 2) {
					destino = destino.substring(2);
					destino = StringHelper.preencherStringEspacoEsquerda(destino, 5);
				} else {
					destino = StringHelper.preencherStringEspacoEsquerda(destino, 5);
				}

				String motivocancelacion = null;
				String valorMulta = null;
				if (isCancelados) {
					SiglaMotivoCancelacion sigla = SiglaMotivoCancelacion.valueOf(item.getMotivocancelacion());
					motivocancelacion = StringHelper.preencherStringEspacoEsquerda(sigla.toString(), 20);
					valorMulta = UtiliteriasFiscal.formataZeroDecimal(item.getValorMulta(), 15);
					brancos = StringHelper.preencherStringEspacoEsquerda(null, 167);
				}

				seq++;
				String status = StringHelper.preencherStringEspacoEsquerda(item.getStatus(), 1);
				String claseServicio = StringHelper.preencherStringEspacoDireita(item.getClaseServicio(), 30);
				String seqHeader = StringHelper.preencherZeroEsquerda(Integer.valueOf(seq).toString(), 6);

				header = UtiliteriasFiscal.headerDocumentoFiscal("1", data, cnpjEcf, coo, serie, especie, codigoCliente,
						filialCliente, condicaoPagamento, valorTotalDocumanto, valorItens, aliquota, imposto,
						valorPIS, valorCofins, valorCSLL, totalICMSIsento, totalICMSNaotributado, origenUf, origen,
						destinoUf, destino, null, null, status, motivocancelacion, valorMulta, brancos, claseServicio, seqHeader);

				/*
				 * Item da importacion Fiscal ECF
				 */
				int seqItem = 1;
				for (ItemFiscalVO subItens : item.getItensFiscais()) {
					String itemDoc = montarItensFiscais(subItens, seq++, seqItem);
					itensDocs.add(itemDoc);
					qtdItens++;
					seqItem++;
				}

				grabarHeaderItens(gravarArq, header, itensDocs);

			}

			seq++;
			String qtdeDocGerados = StringHelper.preencherZeroEsquerda(qtdDoc.toString(), 6);
			String qtdeItensDocGerados = StringHelper.preencherZeroEsquerda(qtdItens.toString(), 6);
			String brancos381 = StringHelper.preencherStringEspacoEsquerda(null, 381);
			String seqFechamento = StringHelper.preencherZeroEsquerda(seq.toString(), 6);

			String fechamento = UtiliteriasFiscal.fechamentoDeArquivo("3", qtdeDocGerados, qtdeItensDocGerados, brancos381, seqFechamento);
			gravarArq.print(fechamento + UtiliteriasFiscal.QUEBRA_LINHA);

			gravarArq.close();
			return arquivo;

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

		return null;
	}

	private HashMap<String, String> getAliquotaBaseCalculo(ImportacionFiscalVO fiscal) {

		HashMap<String, String> resp = new HashMap<String, String>();

		String aliquota = null;
		String imposto = null;
		String totalICMSIsento = null;
		String totalICMSNaotributado = null;

		for (ItemFiscalVO item : fiscal.getItensFiscais()) {

			BigDecimal valorItem = BigDecimal.ZERO;
			String codProduto = StringHelper.preencherStringEspacoEsquerda(item.getCodProduto(), 15);
			// VALIDA TARIFA
			if (codProduto.indexOf("TA") >= 0) {
				valorItem = item.getValorTarifa() == null ? valorItem : item.getValorTarifa();
				if (valorItem.equals(BigDecimal.ZERO))
					valorItem = BigDecimal.ONE;

				// TAXA DE EMBARQUE
			} else if (codProduto.indexOf("TX") >= 0) {
				valorItem = item.getValorEmbarque() == null ? valorItem : item.getValorEmbarque();

				// PEDAGIO
			} else if (codProduto.indexOf("PE") >= 0) {
				valorItem = item.getValorPedagio() == null ? valorItem : item.getValorPedagio();

				// SEGURO
			} else if (codProduto.indexOf("SE") >= 0) {
				valorItem = item.getValorSeguro() == null ? valorItem : item.getValorSeguro();
			}

			try {
				valorItem = UtiliteriasFiscal.arredondar(valorItem);
				item.setValorItem(new BigDecimal(UtiliteriasFiscal.formataZeroDecimal(valorItem, 15)));
			} catch (Exception e) {
				log.error("ERROR: " + item.toString(), e);
				item.setValorItem(new BigDecimal(UtiliteriasFiscal.formataZeroDecimal(BigDecimal.ZERO, 15)));
			}

			HashMap<String, BigDecimal> aliquotaBaseCalculo = new HashMap<String, BigDecimal>(0);

			// Verificando se é um produto tributável. Formato: XXTYYYY (XX - Posicao / YYYY - Aliquota)
			String repTributado = item.getRepTributado() == null ? SituacaoTributaria.NAO_TRIBUTADO.getValue() : item.getRepTributado();
			if (repTributado.length() == 7 && repTributado.substring(2, 3).equals(SituacaoTributaria.TRIBUTADO.getValue())) {

				String tipoPassagem = item.getTipoPassagem();

				if (tipoPassagem == null) {
					tipoPassagem = "E";
				}

				String key = tipoPassagem + item.getRepTributado().substring(3, 7);

				if (!aliquotaBaseCalculo.containsKey(key)) {
					aliquotaBaseCalculo.put(key, BigDecimal.ZERO);
				}

				BigDecimal soma = item.getValorItem().divide(BigDecimal.TEN.multiply(BigDecimal.TEN));
				aliquotaBaseCalculo.put(key, soma.add(aliquotaBaseCalculo.get(key)));

			} else if (repTributado.equals(SituacaoTributaria.NAO_TRIBUTADO.getValue())) {

				BigDecimal soma = item.getValorItem();
				totalICMSNaotributado = soma.toString();

				if (totalICMSNaotributado.length() < 14) {
					totalICMSNaotributado = StringHelper.preencherZeroEsquerda(totalICMSNaotributado, 14);
				}

			}

			for (String key : aliquotaBaseCalculo.keySet()) {
				aliquota = key.substring(1, 5);

				BigDecimal aliquotaCalc = BigDecimal.valueOf(Double.valueOf(aliquota) / UtiliteriasFiscal.CEM.doubleValue());
				aliquotaCalc = UtiliteriasFiscal.arredondar(aliquotaCalc);

				BigDecimal baseCalculo = aliquotaBaseCalculo.get(key);
				baseCalculo = UtiliteriasFiscal.arredondar(baseCalculo);

				BigDecimal valorImposto = baseCalculo.multiply(aliquotaCalc.divide(UtiliteriasFiscal.CEM));
				valorImposto = UtiliteriasFiscal.arredondar(valorImposto);

				imposto = UtiliteriasFiscal.formataZeroDecimal(valorImposto, 14);
				aliquota = UtiliteriasFiscal.formataZeroDecimal(aliquotaCalc, 14);
			}

			boolean inconsistente = item.getInconsistencia() == null ? false : item.getInconsistencia();
			if (inconsistente) {
				if (codProduto.indexOf("TA") >= 0) {
					BigDecimal aliquotaCalc = item.getImpostoEstado() == null ? BigDecimal.ZERO : item.getImpostoEstado();
					aliquotaCalc = UtiliteriasFiscal.arredondar(aliquotaCalc);

					BigDecimal baseCalculo = valorItem;
					baseCalculo = UtiliteriasFiscal.arredondar(baseCalculo);

					BigDecimal valorImposto = baseCalculo.multiply(aliquotaCalc.divide(UtiliteriasFiscal.CEM));
					valorImposto = UtiliteriasFiscal.arredondar(valorImposto);

					imposto = UtiliteriasFiscal.formataZeroDecimal(valorImposto, 14);
					aliquota = UtiliteriasFiscal.formataZeroDecimal(aliquotaCalc, 14);
					totalICMSIsento = null;
					totalICMSNaotributado = null;
				}
			}

		}
		if (StringUtils.isBlank(aliquota))
			aliquota = StringHelper.preencherZeroEsquerda("", 14);

		if (StringUtils.isBlank(imposto))
			imposto = StringHelper.preencherZeroEsquerda("", 14);

		if (StringUtils.isBlank(totalICMSIsento))
			totalICMSIsento = StringHelper.preencherZeroEsquerda("", 14);

		if (StringUtils.isBlank(totalICMSNaotributado))
			totalICMSNaotributado = StringHelper.preencherZeroEsquerda("", 14);

		resp.put("aliquota", aliquota);
		resp.put("imposto", imposto);
		resp.put("totalICMSIsento", totalICMSIsento);
		resp.put("totalICMSNaotributado", totalICMSNaotributado);

		return resp;
	}

	private String montarItensFiscais(ItemFiscalVO item, Integer seq, Integer seqItem) {

		String tipoPassagem = null;

		String repTributado = item.getRepTributado() == null ? SituacaoTributaria.NAO_TRIBUTADO.getValue() : item.getRepTributado();
		if (repTributado.length() == 7 && repTributado.substring(2, 3).equals(SituacaoTributaria.TRIBUTADO.getValue())) {
			tipoPassagem = item.getTipoPassagem();

			if (tipoPassagem == null)
				tipoPassagem = "E";

		} else {
			tipoPassagem = "E";
		}

		String numItem = StringHelper.preencherZeroEsquerda(seqItem.toString(), 3);

		String cfop = null;
		if (tipoPassagem.equals("E")) {
			cfop = StringHelper.preencherStringEspacoDireita("6357", 5);
		} else if (tipoPassagem.equals("M")) {
			cfop = StringHelper.preencherStringEspacoDireita("5357", 5);
		}

		String codigoTES = StringHelper.preencherStringEsquerda(null, 3, "9");
		String codProduto = StringHelper.preencherStringEspacoEsquerda(item.getCodProduto(), 15);
		String unidade = "UN";
		String quantidade = "001";

		// TODO: A forma de enviar o valor do item é baseada no codProduto, pelo fato da FISCAL_R5 estar gravando os registros de tarifa errado
		BigDecimal valorItem = BigDecimal.ZERO;
		// VALIDA TARIFA
		if (codProduto.indexOf("TA") >= 0) {
			valorItem = item.getValorTarifa() == null ? valorItem : item.getValorTarifa();
			if (valorItem.equals(BigDecimal.ZERO))
				valorItem = BigDecimal.ONE.divide(UtiliteriasFiscal.CEM);

			// TAXA DE EMBARQUE
		} else if (codProduto.indexOf("TX") >= 0) {
			valorItem = item.getValorEmbarque() == null ? valorItem : item.getValorEmbarque();

			// PEDAGIO
		} else if (codProduto.indexOf("PE") >= 0) {
			valorItem = item.getValorPedagio() == null ? valorItem : item.getValorPedagio();

			// SEGURO
		} else if (codProduto.indexOf("SE") >= 0) {
			valorItem = item.getValorSeguro() == null ? valorItem : item.getValorSeguro();
		}

		String valorUnitario = null;
		try {
			valorItem = UtiliteriasFiscal.arredondar(valorItem);
			valorUnitario = UtiliteriasFiscal.formataZeroDecimal(valorItem, 15);
			item.setValorItem(new BigDecimal(valorUnitario));
		} catch (Exception e) {
			log.error("ERROR: " + item.toString(), e);
			valorUnitario = UtiliteriasFiscal.formataZeroDecimal(BigDecimal.ZERO, 15);
			item.setValorItem(new BigDecimal(valorUnitario));
		}

		String valorTotal = valorUnitario;
		String aliquotaItem = StringHelper.preencherZeroEsquerda("", 7);
		String impostoItem = StringHelper.preencherZeroEsquerda("", 15);
		String totalICMSIsentoItem = StringHelper.preencherZeroEsquerda("", 15);
		String totalICMSNaotributadoItem = StringHelper.preencherZeroEsquerda("", 15);

		HashMap<String, BigDecimal> aliquotaItens = new HashMap<String, BigDecimal>(0);

		// Verificando se é um produto tributável. Formato: XXTYYYY (XX - Posicao / YYYY - Aliquota)
		if (repTributado.length() == 7 && repTributado.substring(2, 3).equals(SituacaoTributaria.TRIBUTADO.getValue())) {

			String key = tipoPassagem + item.getRepTributado().substring(3, 7);

			if (!aliquotaItens.containsKey(key)) {
				aliquotaItens.put(key, BigDecimal.ZERO);
			}

			BigDecimal soma = item.getValorItem().divide(BigDecimal.TEN.multiply(BigDecimal.TEN));
			aliquotaItens.put(key, soma.add(aliquotaItens.get(key)));

		} else if (repTributado.equals(SituacaoTributaria.NAO_TRIBUTADO.getValue())) {

			BigDecimal soma = item.getValorItem();
			totalICMSNaotributadoItem = StringHelper.preencherZeroEsquerda(soma.toString(), 15);
		}

		for (String key : aliquotaItens.keySet()) {
			aliquotaItem = key.substring(1, 5);

			BigDecimal aliquotaCalc = BigDecimal.valueOf(Double.valueOf(aliquotaItem) / UtiliteriasFiscal.CEM.doubleValue());
			aliquotaCalc = UtiliteriasFiscal.arredondar(aliquotaCalc);

			BigDecimal baseCalculo = aliquotaItens.get(key);
			baseCalculo = UtiliteriasFiscal.arredondar(baseCalculo);

			BigDecimal valorImposto = baseCalculo.multiply(aliquotaCalc.divide(UtiliteriasFiscal.CEM));
			valorImposto = UtiliteriasFiscal.arredondar(valorImposto);

			impostoItem = UtiliteriasFiscal.formataZeroDecimal(valorImposto, 15);
			aliquotaItem = UtiliteriasFiscal.formataZeroDecimal(null, 7);
		}

		boolean inconsistente = item.getInconsistencia() == null ? false : item.getInconsistencia();
		if (inconsistente) {
			if (codProduto.indexOf("TA") >= 0) {
				BigDecimal aliquotaCalc = item.getImpostoEstado() == null ? BigDecimal.ZERO : item.getImpostoEstado();
				aliquotaCalc = UtiliteriasFiscal.arredondar(aliquotaCalc);

				BigDecimal baseCalculo = valorItem;
				baseCalculo = UtiliteriasFiscal.arredondar(baseCalculo);

				BigDecimal valorImposto = baseCalculo.multiply(aliquotaCalc.divide(UtiliteriasFiscal.CEM));
				valorImposto = UtiliteriasFiscal.arredondar(valorImposto);

				impostoItem = UtiliteriasFiscal.formataZeroDecimal(valorImposto, 15);
				aliquotaItem = UtiliteriasFiscal.formataZeroDecimal(null, 7);
				totalICMSNaotributadoItem = StringHelper.preencherZeroEsquerda("", 15);
			}
		}

		String aliquotaPIS = StringHelper.preencherZeroEsquerda("", 7);
		String valorPIS = StringHelper.preencherZeroEsquerda("", 15);
		String aliquotaCofins = StringHelper.preencherZeroEsquerda("", 7);
		String valorCofins = StringHelper.preencherZeroEsquerda("", 15);
		String aliquotaCSLL = StringHelper.preencherZeroEsquerda("", 7);
		String valorCSLL = StringHelper.preencherZeroEsquerda("", 15);
		String aliquotaISS = StringHelper.preencherZeroEsquerda("", 7);
		String valorISS = StringHelper.preencherZeroEsquerda("", 15);

		String numeroPDV = StringHelper.preencherStringEspacoDireita(item.getNumpdv(), 10);
		String numeroSeriePDV = StringHelper.preencherStringEspacoDireita(item.getNumImpressora(), 20);
		String modeloImpressora = StringHelper.preencherStringEspacoDireita(item.getModeloImpressora(), 40);
		String numCaixa = StringHelper.preencherStringEspacoDireita(item.getNumCaixa(), 10);
		String status = StringHelper.preencherStringEspacoEsquerda(item.getStatus(), 1);

		String coo = null;
		String serie = null;

		coo = StringHelper.preencherStringEspacoDireita(item.getCoo(), 9);
		serie = item.getNumImpressora();
		if (serie.length() >= 20) {
			serie = serie.substring(17);
			serie = StringHelper.preencherStringEspacoEsquerda(serie, 3);
		} else {
			serie = StringHelper.preencherStringEspacoEsquerda(null, 3);
		}

		String brancos99 = StringHelper.preencherStringEspacoEsquerda(null, 99);

		seq++;
		String sequencial = StringHelper.preencherZeroEsquerda(seq.toString(), 6);

		String itemDoc = UtiliteriasFiscal.itensDocumentoFiscal("2", numItem, cfop, codigoTES, codProduto,
				unidade, quantidade, valorUnitario, valorTotal, aliquotaItem, impostoItem,
				aliquotaPIS, valorPIS, aliquotaCofins, valorCofins, aliquotaCSLL, valorCSLL,
				aliquotaISS, valorISS, totalICMSIsentoItem, totalICMSNaotributadoItem,
				numeroPDV, numeroSeriePDV, modeloImpressora, numCaixa, status, coo, serie,
				brancos99, sequencial);
		return itemDoc;

	}

	private void grabarHeaderItens(PrintWriter gravarArq, String header, List<String> itensDocs) {
		gravarArq.print(header + UtiliteriasFiscal.QUEBRA_LINHA);

		for (String doc : itensDocs) {
			gravarArq.print(doc + UtiliteriasFiscal.QUEBRA_LINHA);
		}
	}

}
