package com.xxfc.platform.order.pojo.order;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.xxfc.platform.order.entity.OrderItem;
import com.xxfc.platform.vehicle.feign.VehicleFeign;
import com.xxfc.platform.vehicle.pojo.dto.VehicleModelCalendarPriceDTO;
import com.xxfc.platform.vehicle.pojo.dto.order.VMCalendarPriceCostDTO;
import lombok.Data;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;

@Data
public class VehicleItemDTO extends OrderItem {
    public static final int topNum = 2;
    //已抵消天数
    private Integer offsetNum = 0;

    //免费金额
    private BigDecimal freeAmount;

    //标记是否单价一样
    private Integer sameUnitPrice = 1;

    public BigDecimal calculateVehicleUnitPrice(BigDecimal vehicleAmount, BigDecimal metaVehicleAmount, Boolean isSetRealAmount) {
        if(isSetRealAmount) {
            setRealAmount(vehicleAmount);
        }

        BigDecimal unitPrice = BigDecimal.ZERO;
        BigDecimal metaUnitPrice = BigDecimal.ZERO;

        if(getCalculateNum() > 0) {
            unitPrice = vehicleAmount.divide(new BigDecimal(getCalculateNum()+ ""), 2, RoundingMode.HALF_UP);
            metaUnitPrice = metaVehicleAmount.divide(new BigDecimal(getCalculateNum()+ ""), 2, RoundingMode.HALF_UP);
        }

        setUnitPrice(unitPrice);
        setMetaUnitPrice(metaUnitPrice);

        return unitPrice;
    }

    public BigDecimal getCutAmount() {
        List<VMCalendarPriceCostDTO> vmcpds = getVehicleDetail();
        if(CollUtil.isEmpty(vmcpds)){
            return super.getCutAmount();
        }
        BigDecimal cutAmount = BigDecimal.ZERO;
//        for(int i = 0; i < getCutNum(); i++) {
        for(VMCalendarPriceCostDTO vmcpd : vmcpds) {
            cutAmount = cutAmount.add(vmcpd.getFreeAmount());
        }
        return cutAmount;
    }

    public List<VMCalendarPriceCostDTO> getVehicleDetail() {
        if(StrUtil.isBlank(getDetail())) {
            return CollUtil.newArrayList();
        }
        return JSONUtil.toList(JSONUtil.parseArray(getDetail()), VMCalendarPriceCostDTO.class);
    }

    public BigDecimal getBuyAmount() {
        List<VMCalendarPriceCostDTO> vmcpds = getVehicleDetail();
        if(CollUtil.isEmpty(vmcpds)){
            return super.getBuyAmount();
        }
        BigDecimal buyAmount = BigDecimal.ZERO;
        for(int i = 0; i < getBuyNum(); i++) {
        //for(VMCalendarPriceCostDTO vmcpd : vmcpds) {
            buyAmount = buyAmount.add(vmcpds.get(i).getPrice());
        }
        return buyAmount;
    }

    public BigDecimal getTopAmount(Integer useDays) {
        List<VMCalendarPriceCostDTO> vmcpds = getVehicleDetail();
        if(CollUtil.isEmpty(vmcpds)){
            return getUnitPrice().multiply(new BigDecimal(topNum+ ""));
        }
        BigDecimal topAmount = BigDecimal.ZERO;
        for(int i = useDays; i < getTotalNum(); i++) {
            if((i - useDays) >= topNum) {
                break;
            }else {
                topAmount = topAmount.add(vmcpds.get(i).getPrice());
            }
        }

        //未用天数 小于 topNum
        if(getTotalNum() - useDays < topNum) {
            Integer residue = getTotalNum() - useDays;
            topAmount = topAmount.add(vmcpds.get(vmcpds.size() - 1).getPrice().multiply(new BigDecimal((topNum - residue) + "")));
        }
        return topAmount;
    }

    public BigDecimal getUsedAmount(Integer useDays) {
        List<VMCalendarPriceCostDTO> vmcpds = getVehicleDetail();
        if(useDays > getTotalNum()) {
            useDays = getTotalNum();
        }
        if(CollUtil.isEmpty(vmcpds)){
            return getUnitPrice().multiply(new BigDecimal(useDays+ ""));
        }

        BigDecimal usedAmount = BigDecimal.ZERO;
        for(int i = 0; i < useDays; i++) {
            usedAmount = usedAmount.add(vmcpds.get(i).getPrice());
        }
        return usedAmount;
    }

//    public BigDecimal getUsedAmountHasDelay(Integer useDays, List<VMCalendarPriceCostDTO> delayAmountList) {
//
//        BigDecimal usedAmount = getUsedAmount(useDays);
//        if((useDays - getTotalNum()) > 0) {
//            Integer delayAddDays = useDays - getTotalNum();
//            if(delayAddDays > delayAmountList.size()) {
//                delayAddDays = delayAmountList.size();
//            }
//
//            for(int i = 0; i < delayAddDays; i++) {
//                usedAmount = usedAmount.add(delayAmountList.get(i).getPrice());
//            }
//        }
//
//        return usedAmount;
//    }

    //由于免费天数可以抵消不是完整的天数，所以处理比较不同
    public BigDecimal getFreeAmount(Integer offsetDay) {
        List<VMCalendarPriceCostDTO> vmcpds = getVehicleDetail();
        if(CollUtil.isEmpty(vmcpds)){
            if(null == offsetDay) {
                return getUnitPrice().multiply(new BigDecimal(getCutNum()+ ""));
            }else {
                return getUnitPrice().multiply(new BigDecimal(offsetDay+ ""));
            }
        }

        BigDecimal freeAmount = BigDecimal.ZERO;
        if(null != offsetDay) {
            for(int i = 0; i < offsetDay; i++) {
                freeAmount = freeAmount.add(vmcpds.get(i).getFreeAmount());
            }
        }else {
            for(VMCalendarPriceCostDTO vmcpcd : vmcpds) {
                freeAmount = freeAmount.add(vmcpcd.getFreeAmount());
            }
        }
        return freeAmount;
    }

    public Integer mapFreeDays(Integer userDays) {
        List<VMCalendarPriceCostDTO> vmcpds = getVehicleDetail();
        if(userDays > getTotalNum()) {
            userDays = getTotalNum();
        }
        if(CollUtil.isEmpty(vmcpds)){
            return userDays;
        }

        Integer mapFreeDays = 0;
        for(int i = 0; i < userDays; i++) {
            mapFreeDays += vmcpds.get(i).getFreeDays();
        }
        return mapFreeDays;
    }

    public void initDetail() {
        if(StrUtil.isNotBlank(getDetail())) {
            List<VehicleModelCalendarPriceDTO> metaList = JSONUtil.toList(JSONUtil.parseArray(getDetail()), VehicleModelCalendarPriceDTO.class);
            //计算消费金额
            List<VMCalendarPriceCostDTO> list = Convert.toList(VMCalendarPriceCostDTO.class, metaList);
//            ParamDTO paramDTO = initParam(ableFreeDays, list);
            BigDecimal tempUnitPrice = null;
            this.sameUnitPrice = 1;
            for(VMCalendarPriceCostDTO dto : list) {
                if(null == tempUnitPrice) {
                    tempUnitPrice = dto.getPrice();
                }else if( !tempUnitPrice.equals(dto.getPrice())) {
                    this.sameUnitPrice = 0;
                }
                //直接设置价格
                dto.setFreeAndConsumeAmount(dto.getPrice(), BigDecimal.ZERO);
            }
            setCutNum(0);
            setOffsetNum(0);
            setDetail(JSONUtil.parseArray(list).toString());
        }
    }

    public void initDetail(Integer ableFreeDays) {
        if(StrUtil.isNotBlank(getDetail())) {
            List<VehicleModelCalendarPriceDTO> metaList = JSONUtil.toList(JSONUtil.parseArray(getDetail()), VehicleModelCalendarPriceDTO.class);
            //计算消费金额
            List<VMCalendarPriceCostDTO> list = Convert.toList(VMCalendarPriceCostDTO.class, metaList);
            ParamDTO paramDTO = initParam(ableFreeDays, list);
            this.sameUnitPrice = paramDTO.getSameUnitPrice();
            setCutNum(paramDTO.getFreeNum());
            setOffsetNum(paramDTO.getOffsetNum());
            setDetail(JSONUtil.parseArray(list).toString());
        }
    }

    public ParamDTO initParam(Integer ableFreeDays, List<VMCalendarPriceCostDTO> list) {
        ParamDTO paramDTO = new ParamDTO();
        //循环价格列表 获得对应消耗的免费天数
            //循环已标记的已使用免费天数
        Integer cycleNum = 0;
        BigDecimal tempUnitPrice = null;
        for(VMCalendarPriceCostDTO dto : list) {
            if(null == tempUnitPrice) {
                tempUnitPrice = dto.getPrice();
            }else if( !tempUnitPrice.equals(dto.getPrice())) {
                paramDTO.setSameUnitPrice(0);
            }
            if(ableFreeDays > cycleNum && cycleNum+ dto.getFreeDays() > ableFreeDays) { //本次累加天数 大于 可用免费天数
                paramDTO.setFreeNum(ableFreeDays);

                //分子
                Integer up = (ableFreeDays - cycleNum);
                //分母
                Integer down = dto.getFreeDays();
                //设置当前生效免费天数
                dto.setValidFreeDays(up);
                //根据百分比计算消费价格
                dto.setFreeAndConsumeAmount(dto.getPrice(), dto.getPrice().multiply(
                    new BigDecimal(up+ "").divide(new BigDecimal(down+ ""), 2, RoundingMode.HALF_UP))
                    .setScale(2, RoundingMode.HALF_UP));
                paramDTO.setFreeAmount(paramDTO.getFreeAmount().add(dto.getFreeAmount()));
            }else if(ableFreeDays > cycleNum){ //本次累加天数 小于等于 可用免费天数
                paramDTO.setFreeNum(paramDTO.getFreeNum()+ dto.getFreeDays());
                //直接设置价格
                dto.setFreeAndConsumeAmount(dto.getPrice(), dto.getPrice());
                dto.setValidFreeDays(dto.getFreeDays());
                paramDTO.offsetNum += 1;
            }else { //上次累加天数 大于 可用天数
                //直接设置价格
                dto.setFreeAndConsumeAmount(dto.getPrice(), BigDecimal.ZERO);
            }
            cycleNum += dto.getFreeDays();
        }
        return paramDTO;
    }

    @Data
    public class ParamDTO {
        //已抵消天数
        private Integer offsetNum = 0;

        //标记是否单价一样
        private Integer sameUnitPrice = 1;

        //免费数量
        private Integer freeNum = 0;

        //免费金额
        private BigDecimal freeAmount = BigDecimal.ZERO;
    }
}
