package com.fp.general.rates.rules;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import com.fp.common.helper.Constant;
import com.fp.dto.rules.TransactionRule;
import com.fp.dto.save.SaveRequest;
import com.fp.general.exception.GeneralException;
import com.fp.persistence.commondb.PersistenceHelper;
import com.fp.persistence.pgeneral.product.rate.TgeneSubProductRate;

/**
 * Clase que se encarga de verificar traslape en montos de los cargos.
 * 
 * @author Angel Merchan.
 * @version 2.1
 * 
 */
@SuppressWarnings("serial")
public class VerifyOverlapSubProductRatesAmount extends TransactionRule {

    @Override
    public SaveRequest normalProcess(SaveRequest pSaveRequest) throws Exception {
        if (pSaveRequest.getSaveBean("TGENESUBPRODUCTRATE") != null) {
            this.validateTgeneSubProductRates(pSaveRequest);
        }

        return pSaveRequest;
    }

    private void validateTgeneSubProductRates(SaveRequest pSaveRequest) throws Exception {
        String modulecode = pSaveRequest.get("modulecode").toString();
        String productcode = pSaveRequest.get("productcode").toString();
        String subproductcode = pSaveRequest.get("subproductcode").toString();
        String currencycode = pSaveRequest.get("currencycode").toString();
        Integer company = pSaveRequest.getCompany();

        List<Object> lSubProductRatesgesModified = pSaveRequest.getSaveBeanModifiedRecords("TGENESUBPRODUCTRATE");
        List<Object> lSubProductRatesDeleted = pSaveRequest.getSaveBeanDeletedRecords("TGENESUBPRODUCTRATE");
        List<TgeneSubProductRate> listSubProductRatesDatabase = TgeneSubProductRate.find(PersistenceHelper.getEntityManager(), modulecode,
                productcode, subproductcode, currencycode, company);
        List<TgeneSubProductRate> listSubProductRatesFinal = new ArrayList<TgeneSubProductRate>();

        listSubProductRatesFinal = Constant.getFinalList(listSubProductRatesDatabase,
                Constant.convertList(lSubProductRatesgesModified, TgeneSubProductRate.class),
                Constant.convertList(lSubProductRatesDeleted, TgeneSubProductRate.class));

        // Validar traslape de plazo
        for (int i = 0; i < listSubProductRatesFinal.size(); i++) {
            TgeneSubProductRate prodratesfinal = listSubProductRatesFinal.get(i);
            this.validateOverlapTerm(prodratesfinal, i + 1, listSubProductRatesFinal);
        }

        // Validar traslape de monto por plazo
        for (int i = 0; i < listSubProductRatesFinal.size(); i++) {
            TgeneSubProductRate prodratesfinal = listSubProductRatesFinal.get(i);
            this.validateOverlapAmountByTerm(prodratesfinal, i + 1, listSubProductRatesFinal);
        }
    }

    /**
     * 
     * @param prodratesfinal
     * @param index
     * @param listSubProductRateFinal
     * @throws Exception
     */
    private void validateOverlapTerm(TgeneSubProductRate prodratesfinal, int index, List<TgeneSubProductRate> listSubProductRateFinal)
            throws Exception {
        Integer minterm = prodratesfinal.getMinterm();
        Integer maxterm = prodratesfinal.getMaxterm();

        if (minterm.compareTo(maxterm) >= 0) {
            throw new GeneralException("GENE-0050", "EL TÉRMINO MÍNIMO DEBE SER MENOR AL TÉRMINO MÁXIMO EN {0}", "[CARGOS POR TASAS]");
        }

        for (int i = index; i < listSubProductRateFinal.size(); i++) {
            TgeneSubProductRate prodrates = listSubProductRateFinal.get(i);

            if (prodratesfinal.equalsWithoutSequence(prodrates)) {
                Integer mintermcmp = prodrates.getMinterm();
                Integer maxtermcmp = prodrates.getMaxterm();

                if ((minterm.compareTo(mintermcmp) == 0) && (maxterm.compareTo(maxtermcmp) == 0)) {
                    prodrates = null;
                    continue;
                } else if ((minterm.compareTo(maxtermcmp) == 0) || (maxterm.compareTo(mintermcmp) == 0) || (minterm.compareTo(mintermcmp) == 0)
                        || (maxterm.compareTo(maxtermcmp) == 0) || ((minterm.compareTo(mintermcmp) > 0) && (maxterm.compareTo(maxtermcmp) < 0))
                        || ((minterm.compareTo(mintermcmp) < 0) && (maxterm.compareTo(maxtermcmp) > 0))) {
                    throw new GeneralException("GENE-0051", "LOS TÉRMINOS PARA EL TIPO DE BALANCE {0} SE SOBREPONEN EN {1}", prodratesfinal.getPk()
                            .getInterestbalancetype(), "[TASAS POR SUBPRODUCTO]");
                }
            }
            prodrates = null;
        }
    }

    /**
     * Metodo que verifica el traslape de montos de un cargo
     * 
     * @param prodchargesfinal
     * @param index
     * @param listSubProductChargesFinal
     * @throws Exception
     */
    private void validateOverlapAmountByTerm(TgeneSubProductRate prodratesfinal, int index, List<TgeneSubProductRate> listSubProductRateFinal)
            throws Exception {
        BigDecimal minamount = prodratesfinal.getMinamount();
        BigDecimal maxamount = prodratesfinal.getMaxamount();

        if (minamount.compareTo(maxamount) >= 0) {
            throw new GeneralException("GENE-0040", "EL MONTO MÍNIMO DEBE SER MENOR AL MONTO MÁXIMO EN {0}", "[TASAS POR SUBPRODUCTO]");
        }

        for (int i = index; i < listSubProductRateFinal.size(); i++) {
            TgeneSubProductRate prodrates = listSubProductRateFinal.get(i);

            if (prodratesfinal.equalsWithoutSequence(prodrates) && (prodratesfinal.getMinterm().compareTo(prodrates.getMinterm()) == 0)
                    && (prodratesfinal.getMaxterm().compareTo(prodrates.getMaxterm()) == 0)) {
                BigDecimal minamountcmp = prodrates.getMinamount();
                BigDecimal maxamountcmp = prodrates.getMaxamount();

                if (((minamount.compareTo(maxamountcmp) <= 0) && (minamount.compareTo(minamountcmp) >= 0))
                        || ((minamount.compareTo(minamountcmp) >= 0) && (maxamount.compareTo(maxamountcmp) <= 0))
                        || ((minamount.compareTo(minamountcmp) <= 0) && (maxamount.compareTo(maxamountcmp) >= 0))
                        || ((maxamount.compareTo(minamountcmp) >= 0) && (maxamount.compareTo(maxamountcmp) <= 0))) {
                    throw new GeneralException("GENE-0041", "LOS VALORES PARA EL TIPO DE BALANCE {0} SE SOBREPONEN EN {1}", prodratesfinal.getPk()
                            .getInterestbalancetype(), "[TASAS POR SUBPRODUCTO]");
                }
            }
            prodrates = null;
        }
    }

    @Override
    public SaveRequest reverseProcess(SaveRequest pSaveRequest) throws Exception {
        return pSaveRequest;
    }

}
