/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.ctecinf.nfe;

import br.com.ctecinf.model.Produto;
import br.com.ctecinf.Config;
import br.com.ctecinf.Empresa;
import br.com.ctecinf.Utils;
import br.inf.portalfiscal.nfe.v400.autorizacao.ObjectFactory;
import br.inf.portalfiscal.nfe.v400.autorizacao.TEnderEmi;
import br.inf.portalfiscal.nfe.v400.autorizacao.TEndereco;
import br.inf.portalfiscal.nfe.v400.autorizacao.TNFe;
import br.inf.portalfiscal.nfe.v400.autorizacao.TNFe.InfNFe;
import br.inf.portalfiscal.nfe.v400.autorizacao.TUfEmi;
import java.io.File;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Locale;
import javax.xml.bind.annotation.XmlRootElement;

/**
 *
 * @author Cássio Conceição
 * @since 27/05/2019
 * @version 201905
 * @see http://ctecinf.com.br/
 */
@XmlRootElement(name = "NFe")
public class NFCe extends TNFe {

    public NFCe() {

        TEnderEmi enderEmi = new TEnderEmi();

        enderEmi.setCEP(Empresa.getCep());
        enderEmi.setCMun(String.valueOf(Empresa.getMunicipioIBGE()));
        enderEmi.setFone(Empresa.getFone());
        enderEmi.setNro(String.valueOf(Empresa.getNumero()));
        enderEmi.setUF(TUfEmi.valueOf(Empresa.getUf()));
        enderEmi.setXBairro(Empresa.getBairro());
        enderEmi.setXCpl(Empresa.getComplemento());
        enderEmi.setXLgr(Empresa.getLogradouro());
        enderEmi.setXMun(Empresa.getMunicipio());

        TNFe.InfNFe.Emit emit = new TNFe.InfNFe.Emit();
        emit.setCNPJ(Empresa.getCnpj());
        emit.setXFant(Empresa.getNomeFantasia());
        emit.setXNome(Empresa.getRazaoSocial());
        emit.setIE(Empresa.getInscEstadual());

        emit.setCRT("1"); // Simples
        emit.setEnderEmit(enderEmi);

        TNFe.InfNFe.Ide ide = new TNFe.InfNFe.Ide();

        // Configuracao Padrao
        ide.setMod("65"); // NFC-e
        ide.setTpAmb(Config.get("nfe.amb"));
        ide.setCUF(String.valueOf(Empresa.getUfIBGE()));
        ide.setCMunFG(emit.getEnderEmit().getCMun());
        ide.setFinNFe(String.valueOf(1));
        ide.setIdDest(String.valueOf(1));
        ide.setIndFinal(String.valueOf(1));
        ide.setIndPres(String.valueOf(1));
        ide.setNatOp(Empresa.getNatOperacao());
        ide.setProcEmi(String.valueOf(0));
        ide.setSerie(String.valueOf(Empresa.getSerie()));
        ide.setTpEmis(String.valueOf(1));
        ide.setTpImp(String.valueOf(4));
        ide.setTpNF(String.valueOf(1));
        ide.setCNF(Utils.leftPad2(String.valueOf((int) ((double) Math.random() * 99999999)), 8, '0'));

        TNFe.InfNFe.Transp transp = new TNFe.InfNFe.Transp();
        transp.setModFrete("9");

        TNFe.InfNFe.Total.ICMSTot icmsTot = new TNFe.InfNFe.Total.ICMSTot();
        icmsTot.setVBC("0.00");
        icmsTot.setVBCST("0.00");
        icmsTot.setVCOFINS("0.00");
        icmsTot.setVDesc(Utils.decimalFormat2Digits().format(0));
        icmsTot.setVFCP("0.00"); // Novo Combate a Pobreza
        icmsTot.setVFCPST("0.00"); // Novo Combate a Pobreza
        icmsTot.setVFCPSTRet("0.00"); // Novo Combate a Pobreza
        icmsTot.setVFCPUFDest("0.00");
        icmsTot.setVFrete("0.00");
        icmsTot.setVICMS("0.00");
        icmsTot.setVICMSDeson("0.00");
        icmsTot.setVICMSUFDest("0.00");
        icmsTot.setVICMSUFRemet("0.00");
        icmsTot.setVII("0.00");
        icmsTot.setVIPI("0.00");
        icmsTot.setVIPIDevol("0.00"); // Novo
        icmsTot.setVNF(Utils.decimalFormat2Digits().format(0));
        icmsTot.setVOutro("0.00");
        icmsTot.setVPIS("0.00");
        icmsTot.setVProd(Utils.decimalFormat2Digits().format(0));
        icmsTot.setVST("0.00");
        icmsTot.setVSeg("0.00");

        TNFe.InfNFe.Total total = new TNFe.InfNFe.Total();
        total.setICMSTot(icmsTot);

        TNFe.InfNFe.InfAdic infAdic = new TNFe.InfNFe.InfAdic();

        TNFe.InfNFe.Pag pag = new TNFe.InfNFe.Pag();

        infNFe = new TNFe.InfNFe();
        infNFe.setEmit(emit);
        infNFe.setIde(ide);
        infNFe.setTransp(transp);
        infNFe.setTotal(total);
        infNFe.setInfAdic(infAdic);
        infNFe.setPag(pag);

        if (Empresa.getContadorCNPJ() != null && Empresa.getContadorCNPJ().length() == 14) {
            TNFe.InfNFe.AutXML autXML = new TNFe.InfNFe.AutXML();
            autXML.setCNPJ(Empresa.getContadorCNPJ());
            infNFe.getAutXML().add(autXML);
        }

        infNFeSupl = new TNFe.InfNFeSupl();

        super.setInfNFe(infNFe);
        super.setInfNFeSupl(infNFeSupl);
    }

    public void addDest(String cpf, String nome, String email, TEndereco endereco) throws Exception {

        if (cpf == null) {
            throw new Exception("CPF não pode ser nulo.");
        }

        if (!infNFe.getIde().getTpAmb().equals("2")) {

            TNFe.InfNFe.Dest dest = new TNFe.InfNFe.Dest();
            dest.setCPF(cpf.replace(".", "").replace("-", "").trim());

            if (nome != null && !nome.isEmpty()) {
                dest.setXNome(nome.trim());
            }

            if (email != null && !email.isEmpty()) {
                dest.setEmail(email.trim());
            }

            if (endereco != null) {
                dest.setEnderDest(endereco);
            }

            dest.setIndIEDest("9");

            infNFe.setDest(dest);
        }
    }

    public void addDestEstrangeiro(String idEstrangeiro, String nome, String email) throws Exception {

        if (idEstrangeiro == null) {
            throw new Exception("ID Estrangeiro não pode ser nulo.");
        }

        if (!infNFe.getIde().getTpAmb().equals("2")) {

            TNFe.InfNFe.Dest dest = new TNFe.InfNFe.Dest();
            dest.setIdEstrangeiro(idEstrangeiro.trim());

            if (nome != null && !nome.isEmpty()) {
                dest.setXNome(nome.trim());
            }

            if (email != null && !email.isEmpty()) {
                dest.setEmail(email.trim());
            }

            dest.setIndIEDest("9");

            infNFe.setDest(dest);
        }
    }

    /**
     * Adiciona forma de pagamento Dinheiro a NFC-e
     *
     * @param vPag Valor
     */
    public void addPagamentoDinheiro(double vPag) {

        TNFe.InfNFe.Pag.DetPag pag = new TNFe.InfNFe.Pag.DetPag();
        pag.setTPag("01");
        pag.setVPag(Utils.decimalFormat2Digits().format(vPag));

        infNFe.getPag().getDetPag().add(pag);
    }

    /**
     * Adiciona forma de pagamento Cheque a NFC-e
     *
     * @param vPag Valor
     */
    public void addPagamentoCheque(double vPag) {

        TNFe.InfNFe.Pag.DetPag pag = new TNFe.InfNFe.Pag.DetPag();
        pag.setTPag("02");
        pag.setVPag(Utils.decimalFormat2Digits().format(vPag));

        infNFe.getPag().getDetPag().add(pag);
    }

    /**
     * Adiciona forma de pagamento Cartão Crédito a NFC-e
     *
     * @param cartao
     * @param vPag Valor
     */
    public void addPagamentoCartaoCredito(Cartao cartao, double vPag) {

        TNFe.InfNFe.Pag.DetPag.Card card = new TNFe.InfNFe.Pag.DetPag.Card();
        card.setCNPJ(cartao.getCnpj());
        card.setCAut(cartao.getcAut());
        card.setTBand(Utils.leftPad2(cartao.gettBand(), 2, '0'));
        card.setTpIntegra(String.valueOf(cartao.getTpIntegra()));

        TNFe.InfNFe.Pag.DetPag pag = new TNFe.InfNFe.Pag.DetPag();
        pag.setCard(card);
        pag.setTPag("03");
        pag.setVPag(Utils.decimalFormat2Digits().format(vPag));

        infNFe.getPag().getDetPag().add(pag);
    }

    /**
     * Adiciona forma de pagamento Cartão Débito a NFC-e
     *
     * @param cartao
     * @param vPag Valor
     */
    public void addPagamentoCartaoDebito(Cartao cartao, double vPag) {

        TNFe.InfNFe.Pag.DetPag.Card card = new TNFe.InfNFe.Pag.DetPag.Card();
        card.setCNPJ(cartao.getCnpj());
        card.setCAut(cartao.getcAut());
        card.setTBand(Utils.leftPad2(cartao.gettBand(), 2, '0'));
        card.setTpIntegra(String.valueOf(cartao.getTpIntegra()));

        TNFe.InfNFe.Pag.DetPag pag = new TNFe.InfNFe.Pag.DetPag();
        pag.setCard(card);
        pag.setTPag("04");
        pag.setVPag(Utils.decimalFormat2Digits().format(vPag));

        infNFe.getPag().getDetPag().add(pag);
    }

    /**
     * Adiciona forma de pagamento Crediário a NFC-e
     *
     * @param vPag Valor
     */
    public void addPagamentoCrediario(double vPag) {

        TNFe.InfNFe.Pag.DetPag pag = new TNFe.InfNFe.Pag.DetPag();
        pag.setTPag("05");
        pag.setVPag(Utils.decimalFormat2Digits().format(vPag));

        infNFe.getPag().getDetPag().add(pag);
    }

    /**
     * Adiciona forma de pagamento Crediário a NFC-e
     *
     * @param vPag Valor
     */
    public void addPagamentoPix(double vPag) {

        TNFe.InfNFe.Pag.DetPag pag = new TNFe.InfNFe.Pag.DetPag();
        pag.setTPag("17");
        pag.setVPag(Utils.decimalFormat2Digits().format(vPag));

        InfNFe.InfAdic.ObsCont obsCont = new InfNFe.InfAdic.ObsCont();
        obsCont.setXCampo("tPix");
        obsCont.setXTexto("1");

        infNFe.getPag().getDetPag().add(pag);
        infNFe.getInfAdic().getObsCont().add(obsCont);
    }

    /**
     * Adiciona forma de pagamento Crediário a NFC-e
     *
     * @param vPag Valor
     */
    public void addPagamentoDeposito(double vPag) {

        TNFe.InfNFe.Pag.DetPag pag = new TNFe.InfNFe.Pag.DetPag();
        pag.setTPag("16");
        pag.setVPag(Utils.decimalFormat2Digits().format(vPag));

        infNFe.getPag().getDetPag().add(pag);
    }

    /**
     * Adiciona forma de pagamento Outros a NFC-e
     *
     * @param vPag Valor
     */
    public void addPagamentoOutros(double vPag) {

        TNFe.InfNFe.Pag.DetPag pag = new TNFe.InfNFe.Pag.DetPag();
        pag.setTPag("99");
        pag.setVPag(Utils.decimalFormat2Digits().format(vPag));

        infNFe.getPag().getDetPag().add(pag);
    }

    /**
     * Forma de pagamento antecipado, na encomenda
     *
     * @param vPag
     */
    public void setPagamentoAntecipado(double vPag) {

        //infNFe.getIde().setNatOp("PAGAMENTO ANTECIPADO");
        
        TNFe.InfNFe.Det.Prod prod = new TNFe.InfNFe.Det.Prod();

        prod.setCProd("CFOP5949");
        prod.setCEAN("SEM GTIN");
        if (infNFe.getDet().isEmpty() && infNFe.getIde().getTpAmb().equals("2")) {
            prod.setXProd("NOTA FISCAL EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL");
        } else {
            prod.setXProd("PAGAMENTO ANTECIPADO");
        }
        prod.setNCM("00000000");
        prod.setCBenef("RS052999");
        prod.setCFOP("5949");
        prod.setUCom("UN");
        prod.setQCom("1");
        prod.setVUnCom(Utils.decimalFormat2Digits().format(vPag));
        prod.setVProd(Utils.decimalFormat2Digits().format(vPag));
        prod.setCEANTrib("SEM GTIN");
        prod.setUTrib("UN");
        prod.setQTrib("1");
        prod.setVUnTrib(Utils.decimalFormat4Digits().format(vPag));
        prod.setIndTot("1");

        // Regime Geral
//        InfNFe.Det.Imposto.ICMS.ICMS90 icmS90 = new InfNFe.Det.Imposto.ICMS.ICMS90();
//        icmS90.setOrig("0");
//        icmS90.setCST("90");
//
        // Simples Nacional
        InfNFe.Det.Imposto.ICMS.ICMSSN900 icmssN900 = new InfNFe.Det.Imposto.ICMS.ICMSSN900();
        icmssN900.setOrig("0");
        icmssN900.setCSOSN("900");

        TNFe.InfNFe.Det.Imposto.ICMS icms = new TNFe.InfNFe.Det.Imposto.ICMS();
        icms.setICMSSN900(icmssN900);

        TNFe.InfNFe.Det.Imposto.PIS.PISOutr pisnt = new TNFe.InfNFe.Det.Imposto.PIS.PISOutr();
        pisnt.setCST("99");
        pisnt.setQBCProd("0.0000");
        pisnt.setVAliqProd("0.0000");
        pisnt.setVPIS("0.00");

        TNFe.InfNFe.Det.Imposto.PIS pis = new TNFe.InfNFe.Det.Imposto.PIS();
        pis.setPISOutr(pisnt);

        TNFe.InfNFe.Det.Imposto.COFINS.COFINSOutr cofinsnt = new TNFe.InfNFe.Det.Imposto.COFINS.COFINSOutr();
        cofinsnt.setCST("99");
        cofinsnt.setQBCProd("0.0000");
        cofinsnt.setVAliqProd("0.0000");
        cofinsnt.setVCOFINS("0.00");

        TNFe.InfNFe.Det.Imposto.COFINS cofins = new TNFe.InfNFe.Det.Imposto.COFINS();
        cofins.setCOFINSOutr(cofinsnt);

        TNFe.InfNFe.Det.Imposto imposto = new TNFe.InfNFe.Det.Imposto();
        imposto.getContent().add(new ObjectFactory().createTNFeInfNFeDetImpostoICMS(icms));
        imposto.getContent().add(new ObjectFactory().createTNFeInfNFeDetImpostoPIS(pis));
        imposto.getContent().add(new ObjectFactory().createTNFeInfNFeDetImpostoCOFINS(cofins));

        TNFe.InfNFe.Det det = new TNFe.InfNFe.Det();
        det.setNItem(String.valueOf(infNFe.getDet().size() + 1));
        det.setProd(prod);
        det.setImposto(imposto);

        infNFe.getDet().add(det);

        infNFe.getTotal().getICMSTot().setVProd(Utils.decimalFormat2Digits().format(vPag));
        infNFe.getTotal().getICMSTot().setVNF(Utils.decimalFormat2Digits().format(vPag));
    }

    /**
     * Adiciona um produto ICMS 102 a NFC-e
     *
     * @param p
     * @param qtde
     * @param desconto
     */
    public void addProduto(Produto p, double qtde, Double desconto) {

        TNFe.InfNFe.Det.Prod prod = new TNFe.InfNFe.Det.Prod();

        prod.setCEAN("SEM GTIN");
        prod.setCEANTrib("SEM GTIN");

        if (infNFe.getDet().isEmpty() && infNFe.getIde().getTpAmb().equals("2")) {
            prod.setCProd("CFOP" + Empresa.getCfopId());
            prod.setXProd("NOTA FISCAL EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL");
        } else {
            prod.setCProd(String.valueOf(p.getId()).trim());
            prod.setXProd(p.getDescricao().trim());
        }

        double vProd = p.getValorUnitario().doubleValue() * qtde;

        prod.setCFOP(String.valueOf(Empresa.getCfopId()).trim());
        prod.setNCM(String.valueOf(p.getNcm().getId()).trim());
        prod.setQCom(Utils.decimalFormat4Digits().format(qtde));
        prod.setQTrib(Utils.decimalFormat4Digits().format(qtde));
        prod.setUCom(p.getUndCom().trim());
        prod.setUTrib(p.getUndCom().trim());
        prod.setVUnCom(Utils.decimalFormat4Digits().format(p.getValorUnitario()));
        prod.setVUnTrib(Utils.decimalFormat4Digits().format(p.getValorUnitario()));
        prod.setVProd(Utils.decimalFormat2Digits().format(vProd));

        if (desconto != null && desconto > 0) {
            prod.setVDesc(Utils.decimalFormat2Digits().format(desconto));
        }

        prod.setIndTot("1");

        TNFe.InfNFe.Det.Imposto.ICMS icms = new TNFe.InfNFe.Det.Imposto.ICMS();

        TNFe.InfNFe.Det.Imposto.ICMS.ICMSSN102 icmssN102 = new TNFe.InfNFe.Det.Imposto.ICMS.ICMSSN102();
        icmssN102.setCSOSN("102");
        icmssN102.setOrig(String.valueOf(Empresa.getIcmsOrigemId()));

        icms.setICMSSN102(icmssN102);

        TNFe.InfNFe.Det.Imposto.PIS.PISOutr pisnt = new TNFe.InfNFe.Det.Imposto.PIS.PISOutr();
        pisnt.setCST("99");
        pisnt.setQBCProd("0.0000");
        pisnt.setVAliqProd("0.0000");
        pisnt.setVPIS("0.00");

        TNFe.InfNFe.Det.Imposto.PIS pis = new TNFe.InfNFe.Det.Imposto.PIS();
        pis.setPISOutr(pisnt);

        TNFe.InfNFe.Det.Imposto.COFINS.COFINSOutr cofinsnt = new TNFe.InfNFe.Det.Imposto.COFINS.COFINSOutr();
        cofinsnt.setCST("99");
        cofinsnt.setQBCProd("0.0000");
        cofinsnt.setVAliqProd("0.0000");
        cofinsnt.setVCOFINS("0.00");

        TNFe.InfNFe.Det.Imposto.COFINS cofins = new TNFe.InfNFe.Det.Imposto.COFINS();
        cofins.setCOFINSOutr(cofinsnt);

        TNFe.InfNFe.Det.Imposto imposto = new TNFe.InfNFe.Det.Imposto();
        imposto.getContent().add(new ObjectFactory().createTNFeInfNFeDetImpostoICMS(icms));
        imposto.getContent().add(new ObjectFactory().createTNFeInfNFeDetImpostoPIS(pis));
        imposto.getContent().add(new ObjectFactory().createTNFeInfNFeDetImpostoCOFINS(cofins));

        TNFe.InfNFe.Det det = new TNFe.InfNFe.Det();
        det.setNItem(String.valueOf(infNFe.getDet().size() + 1));
        det.setProd(prod);
        det.setImposto(imposto);

        infNFe.getDet().add(det);

        double vTot = Double.parseDouble(infNFe.getTotal().getICMSTot().getVProd());

        infNFe.getTotal().getICMSTot().setVProd(Utils.decimalFormat2Digits().format(vProd + vTot));
        infNFe.getTotal().getICMSTot().setVNF(Utils.decimalFormat2Digits().format(vProd + vTot));
    }

    /**
     * Finaliza NFC-e
     *
     * @param troco Valor
     */
    public void finalizar(double troco) {

        double subTotal = Double.parseDouble(infNFe.getTotal().getICMSTot().getVProd());
        double total = subTotal;
        double tributos = Empresa.getAliquota();
        double desconto = 0;

        for (TNFe.InfNFe.Det det : infNFe.getDet()) {
            if (det.getProd().getVDesc() != null) {
                desconto += Double.parseDouble(det.getProd().getVDesc());
            }
        }

        total -= desconto;

        if (troco > 0) {
            for (TNFe.InfNFe.Pag.DetPag pag : infNFe.getPag().getDetPag()) {
                if (pag.getTPag().equals("01") && Double.parseDouble(pag.getVPag()) > troco) {
                    pag.setVPag(Utils.decimalFormat2Digits().format(Double.parseDouble(pag.getVPag()) - troco));
                    break;
                }
            }
        }

        infNFe.getPag().setVTroco(Utils.decimalFormat2Digits().format(troco));
        infNFe.getTotal().getICMSTot().setVDesc(Utils.decimalFormat2Digits().format(desconto));
        infNFe.getTotal().getICMSTot().setVNF(Utils.decimalFormat2Digits().format(total));
        infNFe.getInfAdic().setInfCpl("Documento emitido por ME ou EPP optante pelo Simples Nacional. Tributos Totais Incidentes (Lei Federal 12.741/2012):    " + DecimalFormat.getCurrencyInstance(new Locale("pt", "BR")).format(total * tributos / 100));
    }

    public static File getProcNFePath(Calendar cal) {

        Locale local = new Locale("pt", "BR");

        if (cal == null) {
            cal = Utils.dateFromServer();
        }

        return new File(Config.get("nfe.xml.path"), "xml" + File.separator + cal.get(Calendar.YEAR) + File.separator + cal.getDisplayName(Calendar.MONTH, Calendar.LONG, local));
    }
}
