package com.fp.general.rates.rules;

import java.sql.Date;
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.commondb.helper.APPDates;
import com.fp.persistence.pgeneral.date.TgeneAccountingDateBranch;
import com.fp.persistence.pgeneral.product.rate.TgeneBaseRateDetail;

@SuppressWarnings("serial")
public class ValidateRates extends TransactionRule {

    @Override
    public SaveRequest normalProcess(SaveRequest pSaveRequest) throws Exception {
        String currencycode = pSaveRequest.get("currencycode").toString();
        String baseratecatalog = pSaveRequest.get("baseratecatalog").toString();
        String baseratecatalogcode = pSaveRequest.get("baseratecatalogcode").toString();
        Integer company = pSaveRequest.getCompany();

        List<Object> lRatesMod = pSaveRequest.getSaveBeanModifiedRecords("TGENEBASERATEDETAIL");
        List<Object> lRatesDel = pSaveRequest.getSaveBeanDeletedRecords("TGENEBASERATEDETAIL");
        List<TgeneBaseRateDetail> lRatesDB = TgeneBaseRateDetail.find(PersistenceHelper.getEntityManager(), currencycode, baseratecatalog,
                baseratecatalogcode);

        TgeneAccountingDateBranch d = com.fp.persistence.commondb.db.DataHelper.getInstance().getTgeneAccountingDateBranch(company, 0);

        this.validateDeleted(lRatesDel, lRatesDB, d.getWorkingdate());
        this.validateModified(lRatesMod, lRatesDB, d.getWorkingdate());

        List<TgeneBaseRateDetail> lRatesFinal = Constant.getFinalList(lRatesDB, Constant.convertList(lRatesMod, TgeneBaseRateDetail.class),
                Constant.convertList(lRatesDel, TgeneBaseRateDetail.class));

        // Validar traslape de fechas
        for (int i = 0; i < lRatesFinal.size(); i++) {
            TgeneBaseRateDetail ratedetail = lRatesFinal.get(i);
            this.validateOverlap(ratedetail, i + 1, lRatesFinal);
        }

        return pSaveRequest;
    }

    /**
     * Valida que no se borren registros vigentes y pasados
     * 
     * @param lRatesDel
     * @param lRatesDB
     * @param wdate
     * @throws Exception
     */
    private void validateDeleted(List<Object> lRatesDel, List<TgeneBaseRateDetail> lRatesDB, Date wdate) throws Exception {
        if (lRatesDel != null) {
            for (Object obj : lRatesDel) {
                TgeneBaseRateDetail ratedetaildel = (TgeneBaseRateDetail) obj;
                TgeneBaseRateDetail ratedetailbase = Constant.isInList(lRatesDB, ratedetaildel);
                if (ratedetailbase != null) {
                    int result = this.getDateRange(ratedetailbase.getValidityrate(), ratedetailbase.getExpirationdate(), wdate);
                    if (result <= 0) {
                        throw new GeneralException("GENE-0045", "NO SE PUEDE ELIMINAR TASAS CON FECHA VIGENTE O VENCIDA");
                    }
                }
            }
        }
    }

    /**
     * Valida que solo se ingresen tasas con fechas futuras
     * 
     * @param lRatesMod
     * @param lRatesDB
     * @param wdate
     * @throws Exception
     */
    private void validateModified(List<Object> lRatesMod, List<TgeneBaseRateDetail> lRatesDB, Date wdate) throws Exception {
        if (lRatesMod != null) {
            for (Object obj : lRatesMod) {
                TgeneBaseRateDetail ratedetailmod = (TgeneBaseRateDetail) obj;
                TgeneBaseRateDetail ratedetailbase = Constant.isInList(lRatesDB, ratedetailmod);
                if ((ratedetailbase == null) || Constant.ifYes((String) ratedetailmod.get("isnew"))) {
                    int result = this.getDateRange(ratedetailmod.getValidityrate(), ratedetailmod.getExpirationdate(), wdate);
                    if (result <= 0) {
                        throw new GeneralException("GENE-0046", "SOLO SE PUEDE INGRESAR TASAS CON FECHA FUTURAS");
                    }
                }
            }
        }
    }

    /**
     * Valida que no se translapen las fechas de las tasas
     * 
     * @param ratedetail
     * @param searchIndex
     * @param lRatesFinal
     * @return
     * @throws Exception
     */
    private void validateOverlap(TgeneBaseRateDetail ratedetail, int searchIndex, List<TgeneBaseRateDetail> lRatesFinal) throws Exception {
        for (int i = searchIndex; i < lRatesFinal.size(); i++) {
            TgeneBaseRateDetail ratedetailfinal = lRatesFinal.get(i);
            if (ratedetail.equalsWithoutRateSequence(ratedetailfinal)) {
                int result = this.getDateRange(ratedetail.getValidityrate(), ratedetail.getExpirationdate(), ratedetailfinal.getValidityrate());
                if (result == 0) {
                    throw new GeneralException("GENE-0047", "EXISTE CRUCE DE FECHAS");
                }
            }
        }
    }

    /**
     * Retorna 0 si el parametro actualdate esta dentro del rango, 1 si el rango es > que actualdate, -1 si el rango es
     * menor que actualdate
     * 
     * @param initdate
     * @param enddate
     * @param actualdate
     * @return
     * @throws Exception
     */
    private int getDateRange(Date initdate, Date enddate, Date actualdate) throws Exception {
        APPDates init = new APPDates(initdate);
        APPDates end = new APPDates(enddate);
        APPDates now = new APPDates(actualdate);

        if (init.compareTo(now) > 0) {
            return 1;
        } else if ((now.compareTo(init) >= 0) && (now.compareTo(end) <= 0)) {
            return 0;
        }
        // else if (end.compareTo(now) < 0) {
        // return -1;
        // }
        return -1;
    }

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

}
