package com.ag.account.feeUtil;

import com.ag.entity.account.FeeDetail;
import com.ag.entity.fee.TariffMultistep;
import com.ag.entity.fee.vo.TariffVO;
import com.ag.util.UUIDUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * Created by Administrator on 2017/6/27 0027.
 * 堆存类阶梯算法，不要试图修改
 */
public class MultiStepUtil {

    /*public static void calcAmount(SourceProperty source, FeeDetail account) {
        TariffVO tariff = source.getTariffVO();
        *//*if (cntrProperty.getCustomTariff() != null) {
            tariff = cntrProperty.getCustomTariff();
        } else if(cntrProperty.getBaseTariff() != null) {
            tariff = cntrProperty.getBaseTariff();
        }*//*
        if (tariff == null) {
            return;
        }
        //account.setDwellDays(cntrProperty.getDwellDays());
        getAmount(tariff, account);

    }*/

    /**
     * 阶梯费率算法
     *
     * @param tariff    费率
     * @param feeDetail 目标
     */
    public static void calcAmount(TariffVO tariff, FeeDetail feeDetail) {
        //double days = cntrProperty.getDwellDays();

        List<TariffMultistep> stepList = tariff.getStepList();
        //没有阶梯费率
        if (CollectionUtils.isEmpty(stepList)) {
            //费率 * 堆存天 * 计费吨
            feeDetail.setCalcMoney(tariff.getRate() * feeDetail.getSettleDays() * feeDetail.getQuantity());
            return;
        }
        double amount = 0d;
        feeDetail.setDerateDays(0);
        for (TariffMultistep step : stepList) {

            //减免天（阶梯费率=0）
            if (step.getStepRate() == 0) {
                //account.setDerateDays(step.getEndVal() - step.getStartVal() + 1);
                feeDetail.setDerateDays(step.getEndVal());
            }
            if (feeDetail.getDerateDays() > feeDetail.getSettleDays()) {
                feeDetail.setDerateDays(feeDetail.getSettleDays());
            }
            if (feeDetail.getSettleDays() >= step.getEndVal()) {
                amount += step.getStepRate() * (step.getEndVal() - step.getStartVal() + 1);
                continue;
            }
            if (feeDetail.getSettleDays() >= step.getStartVal() && feeDetail.getSettleDays() <= step.getEndVal()) {
                //account.setDwellDays(account.getDwellDays() - step.getStartVal() + 1);
                int overDay = feeDetail.getSettleDays() - step.getStartVal() + 1;
                amount += step.getStepRate() * overDay;
            }
        }
        feeDetail.setCalcMoney(amount * feeDetail.getQuantity());
        feeDetail.setCalcDays(feeDetail.getSettleDays() - feeDetail.getDerateDays());
        if (feeDetail.getCalcDays() < 0){
            feeDetail.setCalcDays(0);
        }
        //account.setDwellDays(account.getSettleDays() - account.getDerateDays());
    }


    public static List<FeeDetail> calcAmountForList(TariffVO tariff, FeeDetail feeDetail) {
        List<FeeDetail> feeDetails = new ArrayList<>();
        List<TariffMultistep> stepList = tariff.getStepList();

        //没有阶梯费率
        if (CollectionUtils.isEmpty(stepList)) {
            //费率 * 堆存天 * 计费吨
            feeDetail.setCalcMoney(tariff.getRate() * feeDetail.getSettleDays() * feeDetail.getQuantity());
            feeDetails.add(feeDetail);
            return feeDetails;
        } else {
            stepList.sort(Comparator.comparing(TariffMultistep::getStartVal));
        }
        //满N天，费率上调M元，无上限算法 (阶梯费率延伸)
        List<TariffMultistep> steps = tariff.getStepList();
        TariffMultistep realLast = steps.get(steps.size() - 1);
        if (realLast.getEachDay() != null && realLast.getAddRate() != null) {
            while (true) {
                if (addStepObj(tariff, feeDetail)) {
                    break;
                }
            }
        }
        feeDetail.setDerateDays(0);//默认减免天
        for (TariffMultistep step : stepList) {
            //减免天（阶梯费率=0）
            if (step.getStepRate() == 0) {
                //account.setDerateDays(step.getEndVal() - step.getStartVal() + 1);
                feeDetail.setDerateDays(step.getEndVal());//更新减免天
            }
            //first：堆存天 《= 减免天
            if (feeDetail.getSettleDays() <= feeDetail.getDerateDays()) {
                feeDetail.setDerateDays(feeDetail.getSettleDays());//更新减免天
            }
            //second：堆存天 》= 阶梯费率上限
            if (feeDetail.getSettleDays() >= step.getEndVal()) {
                //amount += step.getStepRate() * (step.getEndVal() - step.getStartVal() + 1);
                FeeDetail newDetail = new FeeDetail();
                BeanUtils.copyProperties(feeDetail, newDetail);
                newDetail.setId(UUIDUtil.getUUID());
                newDetail.setActualRate(step.getStepRate());
                newDetail.setCalcDays(step.getEndVal() - step.getStartVal() + 1);
                feeDetails.add(newDetail);
                continue;
            }
            //last：堆存天在阶梯费率范围内的
            if (feeDetail.getSettleDays() >= step.getStartVal() && feeDetail.getSettleDays() <= step.getEndVal()) {
                int calcDay = feeDetail.getSettleDays() - step.getStartVal() + 1;
                //amount += step.getStepRate() * calcDay;
                FeeDetail newDetail = new FeeDetail();
                BeanUtils.copyProperties(feeDetail, newDetail);
                newDetail.setId(UUIDUtil.getUUID());
                newDetail.setActualRate(step.getStepRate());
                newDetail.setCalcDays(calcDay);
                feeDetails.add(newDetail);
            }
        }
        //feeDetail.setCalcMoney(amount * feeDetail.getQuantity());
        //feeDetail.setCalcDays(feeDetail.getSettleDays() - feeDetail.getDerateDays());
        //account.setDwellDays(account.getSettleDays() - account.getDerateDays());
        for (FeeDetail newDetail : feeDetails) {
            newDetail.setStRate(newDetail.getActualRate());
            newDetail.setCalcMoney(newDetail.getActualRate() * newDetail.getCalcDays() * feeDetail.getQuantity());
        }
        return feeDetails;
    }

    private static boolean addStepObj(TariffVO tariff, FeeDetail feeDetail) {
        List<TariffMultistep> steps = tariff.getStepList();
        TariffMultistep last = steps.get(steps.size() - 1);
        if (last.getEndVal() >= feeDetail.getSettleDays()) {
            return true;
        }
        TariffMultistep next = new TariffMultistep();
        next.setStartVal(last.getStartVal() + last.getEachDay());
        next.setEndVal(last.getEndVal() + last.getEachDay());
        next.setStepRate(last.getStepRate() + last.getAddRate());
        next.setEachDay(last.getEachDay());
        next.setAddRate(last.getAddRate());
        steps.add(next);
        return false;
    }

}
