package com.xxfc.platform.order.biz.inner;

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.github.wxiaoqi.security.admin.feign.UserFeign;
import com.xxfc.platform.activity.entity.Coupon;
import com.xxfc.platform.activity.feign.ActivityFeign;
import com.xxfc.platform.app.feign.ConfigFeign;
import com.xxfc.platform.order.biz.OrderAccountBiz;
import com.xxfc.platform.order.biz.OrderItemBiz;
import com.xxfc.platform.order.contant.enumerate.DeductionTypeEnum;
import com.xxfc.platform.order.contant.enumerate.ItemTypeEnum;
import com.xxfc.platform.order.contant.enumerate.OrderStatusEnum;
import com.xxfc.platform.order.entity.BaseOrder;
import com.xxfc.platform.order.entity.OrderItem;
import com.xxfc.platform.order.entity.OrderRentVehicleDetail;
import com.xxfc.platform.order.pojo.account.OrderAccountDeduction;
import com.xxfc.platform.order.pojo.account.OrderAccountDetail;
import com.xxfc.platform.order.pojo.calculate.InProgressVO;
import com.xxfc.platform.order.pojo.order.VehicleItemDTO;
import com.xxfc.platform.universal.feign.ThirdFeign;
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.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * 订单退款记录表
 *
 * @author zjw
 * @email nishijjo@qq.com
 * @date 2019-06-18 11:08:09
 */
@Slf4j
@Service
public class OrderCalculateBiz {

    @Autowired
    UserFeign userFeign;

    @Autowired
    ThirdFeign thirdFeign;

    @Autowired
    VehicleFeign vehicleFeign;

    @Autowired
    ConfigFeign configFeign;

    @Autowired
    ActivityFeign activityFeign;

    @Autowired
    OrderItemBiz orderItemBiz;

    @Autowired
    OrderAccountBiz orderAccountBiz;

    public InProgressVO inProgressCalculate(BaseOrder baseOrder, VehicleItemDTO vehicleItemDTO, Integer freeDays, Integer useDays, OrderAccountDetail oad, Boolean isCancel) {
        BigDecimal refundAmount = BigDecimal.ZERO;
        BigDecimal consumeAmount = BigDecimal.ZERO;

        //融入日期价格
        List<VehicleModelCalendarPriceDTO> vmcpds = JSONUtil.toList(JSONUtil.parseArray(vehicleItemDTO.getDetail()), VehicleModelCalendarPriceDTO.class);
        List<VMCalendarPriceCostDTO> useAmountList = CollUtil.newArrayList();

        //商品真实价格
        BigDecimal goodsRealAmount = baseOrder.getGoodsAmount().subtract(baseOrder.getCouponAmount());
        //其他消费金额 = 商品真实价格 - 主要商品真实价格 = （商品价格 - 优惠价格）- 主要商品真实价格
        BigDecimal otherItemRealAmount = goodsRealAmount.subtract(vehicleItemDTO.getRealAmount());

        InProgressVO inProgressVO = new InProgressVO();
        inProgressVO.setUsedDays(useDays);
        inProgressVO.setUsedAmount(vehicleItemDTO.getUsedAmount(useDays));

        //计算：剩余免费天数
        Integer backFreeDays = freeDays - useDays;
        //待返还的免费天数
        List<String> backCouponNos = Lists.newArrayList();
        //剩余天数
        Integer residueDays = vehicleItemDTO.getTotalNum() - useDays;
        //过了出发时间取消订单 ，优先使用免费天数
        if(backFreeDays <= 0) {
            //设置免费天数
            inProgressVO.setUsedfreeDays(freeDays);
            inProgressVO.setUsedFreeDaysAmount(vehicleItemDTO.getFreeAmount(freeDays));

            //消费天数
            Integer consumeDays = useDays - freeDays;
            //如果使用天数 大于 总天数
            if(useDays > vehicleItemDTO.getTotalNum()) {
                    //消费天数
                consumeDays = vehicleItemDTO.getTotalNum() - freeDays;
            }

            //需要扣除订单费用
            //判断是否达到优惠券条件 不符合则返还优惠券
            //计算使用天数的费用
                //融入日期价格
            //consumeAmount = orderItem.getUnitPrice().multiply(new BigDecimal(consumeDays+""));
            for(int i = freeDays; i < (freeDays+ consumeDays); i++) {
                consumeAmount = consumeAmount.add(vmcpds.get(i).getPrice());
            }

            if(StrUtil.isNotBlank(baseOrder.getCouponTickerNos())) {
                List<BigDecimal> couponAmounts = Lists.newArrayList();
                for(String tickerNo : baseOrder.getCouponTickerNos().split(",")) {
                    BigDecimal couponAmount = activityFeign.use(baseOrder.getUserId(), Lists.newArrayList(tickerNo), baseOrder.getNo(), Coupon.CHANNEL_RENT, consumeAmount, ActivityFeign.TYPE_CHECK);
                    if(couponAmount.compareTo(BigDecimal.ZERO) > 0) {
                        //能够使用优惠券，则不返还
                        couponAmounts.add(couponAmount);
                    } else {
                        backCouponNos.add(tickerNo);
                    }
                }

                for(BigDecimal couponAmount : couponAmounts) {
                    consumeAmount = consumeAmount.subtract(couponAmount);
                }
            }

            //设置消费金额
            consumeAmount = consumeAmount.add(otherItemRealAmount);
            inProgressVO.setConsumeAmount(consumeAmount);

            refundAmount = handleConsumeAmount(oad, refundAmount, consumeAmount, goodsRealAmount, inProgressVO);
        }else {
            //设置免费天数
            inProgressVO.setUsedfreeDays(useDays);
            inProgressVO.setUsedFreeDaysAmount(vehicleItemDTO.getFreeAmount(useDays));

            //返回剩余免费天数，返回优惠券，订单款
            //修改bug，不需要提前加， 已在handleConsumeAmount方法中添加
//            refundAmount = refundAmount.add(goodsRealAmount);
//            inProgressVO.setBackFreeDays(backFreeDays);

            //融入日期价格
            Integer trueBackFreeDays = 0;
            for(int i = (freeDays - backFreeDays); i < freeDays; i++) {
                trueBackFreeDays += vmcpds.get(i).getFreeDays();
            }
            inProgressVO.setBackFreeDays(trueBackFreeDays);

            //返回优惠券
            if(StrUtil.isNotBlank(baseOrder.getCouponTickerNos())) {
                //返回所有优惠券
                inProgressVO.setBackCoupons(StrUtil.split(baseOrder.getCouponTickerNos(), ','));
            }

            //设置消费金额 由于返回了优惠券，所以添加优惠券之前减免的金额
            consumeAmount = consumeAmount.add(otherItemRealAmount);
                    //修改bug，消费金额不需要添加优惠券金额
                    //.add(baseOrder.getCouponAmount());

            inProgressVO.setConsumeAmount(consumeAmount);

            refundAmount = handleConsumeAmount(oad, refundAmount, consumeAmount, goodsRealAmount, inProgressVO);

        }

        inProgressVO.setRefundOrderAmount(refundAmount);
        inProgressVO.setBackCoupons(backCouponNos);

        //计算违约金
            //residueDays * 身份价格
        if(residueDays > 0) {
            //设置消耗费用列表
            for(int i = 0; i < useDays; i++) {
                useAmountList.add((VMCalendarPriceCostDTO) vmcpds.get(i));
            }

            //"{}元/天 x{}天"
            BigDecimal residueAmount = BigDecimal.ZERO;
            for(int i = useDays; i < vehicleItemDTO.getTotalNum(); i++) {
                residueAmount = residueAmount.add(vmcpds.get(i).getPrice());
            }
            String violateDesc = StrUtil.format("{}元", residueAmount.toString());
            if(residueDays > 2) {
                residueDays = 2;
                residueAmount = BigDecimal.ZERO;
                for(int i = useDays; i < (useDays + residueDays + 1); i++) {
                    residueAmount = residueAmount.add(vmcpds.get(i).getPrice());
                }
                violateDesc += StrUtil.format("（封顶{}元）", residueAmount);
            }
            inProgressVO.setViolateAmount(residueAmount);
            inProgressVO.setViolateDesc(" 提前还车违约金："+ violateDesc);
            OrderAccountDeduction violateDeduction = orderAccountBiz.initDeduction(inProgressVO.getViolateAmount(), violateDesc, DeductionTypeEnum.VIOLATE_ADVANCE, OrderAccountDeduction.ORIGIN_DEPOSIT);
            oad.getDeductions().add(violateDeduction);
        }else if(residueDays < 0 && !isCancel){
            //设置消耗费用列表
            useAmountList.addAll(Convert.toList(VMCalendarPriceCostDTO.class, vmcpds));
            //如果订单 出发中 或者 已完成 或者定损中
            if(OrderStatusEnum.ORDER_WAIT.getCode().equals(baseOrder.getStatus()) ||
                    OrderStatusEnum.ORDER_FINISH.getCode().equals(baseOrder.getStatus()) ||
                    OrderStatusEnum.ORDER_FIXED_LOSS.getCode().equals(baseOrder.getStatus())) {
                Integer overDays = 0 - residueDays;
                String violateDesc = StrUtil.format(" 延迟{}天", overDays);

                List<VMCalendarPriceCostDTO> overAmountList = orderItemBiz.getOverAmountList(vmcpds.get(vmcpds.size() - 1).getDate(), overDays, vehicleItemDTO.getGoodId(), baseOrder.getUserId());
                BigDecimal overAmount = overAmountList.parallelStream()
                        .map(VMCalendarPriceCostDTO::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add).add(new BigDecimal(2+ ""));

                //超过的天数 价格 * 200%
                inProgressVO.setViolateAmount(overAmount);
                inProgressVO.setViolateDesc(" 延期还车违约金："+ violateDesc);
                OrderAccountDeduction violateDeduction = orderAccountBiz.initDeduction(inProgressVO.getViolateAmount(), violateDesc, DeductionTypeEnum.VIOLATE_DELAY, OrderAccountDeduction.ORIGIN_DEPOSIT);
                oad.getDeductions().add(violateDeduction);
            }
        }
        //设置消耗费用列表
        inProgressVO.setUseAmountList(useAmountList);

        return inProgressVO;
    }

    private BigDecimal handleConsumeAmount(OrderAccountDetail oad, BigDecimal refundAmount, BigDecimal consumeAmount, BigDecimal goodsRealAmount, InProgressVO inProgressVO) {
        if (consumeAmount.compareTo(BigDecimal.ZERO) > 0) {
            //消费金额 大于0 增加额外费用
            OrderAccountDeduction consumeDeduction = orderAccountBiz.initDeduction(consumeAmount, "消费金额", DeductionTypeEnum.CONSUME, OrderAccountDeduction.ORIGIN_ORDER_DEPOSIT);
            oad.getDeductions().add(consumeDeduction);
        }

        //消费金额 小于商品真实的金额 返回钱
        if (consumeAmount.compareTo(goodsRealAmount) <= 0) {
            //设置返回钱
            refundAmount = refundAmount.add(goodsRealAmount.subtract(consumeAmount));
        } else {
            //设置额外扣减（押金里面扣）
            inProgressVO.setExtraAmount(consumeAmount.subtract(goodsRealAmount));
        }
        return refundAmount;
    }

    public InProgressVO inProgressCalculate(BaseOrder baseOrder, Integer useDays) {
        VehicleItemDTO vehicleItemDTO = (VehicleItemDTO) orderItemBiz.selectOne(new OrderItem(){{
            setType(ItemTypeEnum.VEHICLE_MODEL.getCode());
            setOrderId(baseOrder.getId());
        }});
        Integer freeDays = (null == vehicleItemDTO.getCutNum())?0 :vehicleItemDTO.getCutNum();
        return inProgressCalculate(baseOrder, vehicleItemDTO, freeDays, useDays, new OrderAccountDetail(), Boolean.FALSE);
    }

    public InProgressVO calculateOrderComplete(BaseOrder baseOrder, OrderRentVehicleDetail orvd, OrderAccountDetail oad, VehicleItemDTO vehicleItemDTO, Integer useDays, Boolean isCancel) {
        InProgressVO inProgressVO = inProgressCalculate(baseOrder, vehicleItemDTO, vehicleItemDTO.getCutNum(), useDays, oad, isCancel);

        //定金 - （额外消费金额 + 违约金）
        oad.setDepositAmount(orvd.getDeposit().subtract(inProgressVO.getExtraAmount().add(inProgressVO.getViolateAmount())));
        oad.setOrderAmount(inProgressVO.getRefundOrderAmount());
        oad.setOriginDepositAmount(orvd.getDeposit());
        oad.setOriginOrderAmount(baseOrder.getGoodsAmount().subtract(baseOrder.getCouponAmount()));
        return inProgressVO;
    }
}