
package com.tmerclub.cloud.order.controller.app;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.tmerclub.cloud.api.order.constant.OrderStatus;
import com.tmerclub.cloud.api.vo.EsPageVO;
import com.tmerclub.cloud.common.cache.constant.OrderCacheNames;
import com.tmerclub.cloud.common.cache.util.RedisUtil;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.database.dto.PageDTO;
import com.tmerclub.cloud.common.database.vo.PageVO;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.order.constant.OrderActivityType;
import com.tmerclub.cloud.common.order.constant.OrderType;
import com.tmerclub.cloud.common.order.constant.RefundStatusEnum;
import com.tmerclub.cloud.common.order.constant.ReturnProcessStatusEnum;
import com.tmerclub.cloud.common.order.dto.OrderRefundSearchDTO;
import com.tmerclub.cloud.common.order.vo.EsOrderRefundVO;
import com.tmerclub.cloud.common.order.vo.OrderItemVO;
import com.tmerclub.cloud.common.order.vo.RefundOrderItemVO;
import com.tmerclub.cloud.common.response.ResponseEnum;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.security.AuthUserContext;
import com.tmerclub.cloud.common.util.Arith;
import com.tmerclub.cloud.common.util.BeanUtil;
import com.tmerclub.cloud.common.util.PriceUtil;
import com.tmerclub.cloud.order.constant.PlatformInterventionStatus;
import com.tmerclub.cloud.order.constant.RefundApplyType;
import com.tmerclub.cloud.order.constant.RefundType;
import com.tmerclub.cloud.order.dto.OrderRefundInterventionDTO;
import com.tmerclub.cloud.order.dto.app.OrderRefundDTO;
import com.tmerclub.cloud.order.dto.app.OrderRefundDeliveryDTO;
import com.tmerclub.cloud.order.model.Order;
import com.tmerclub.cloud.order.model.OrderItem;
import com.tmerclub.cloud.order.model.OrderRefund;
import com.tmerclub.cloud.order.model.OrderRefundAddr;
import com.tmerclub.cloud.order.service.OrderItemService;
import com.tmerclub.cloud.order.service.OrderRefundAddrService;
import com.tmerclub.cloud.order.service.OrderRefundService;
import com.tmerclub.cloud.order.service.OrderService;
import com.tmerclub.cloud.order.vo.OrderRefundAddrVO;
import com.tmerclub.cloud.order.vo.OrderRefundVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 订单退款记录信息
 *
 * @author tmerclub
 * @date 2020-12-05 14:13:50
 */
@RestController("appOrderRefundController")
@RequestMapping("/order_refund")
@Tag(name = "app-订单退款记录信息")
public class OrderRefundController {

    private final Logger LOGGER = LoggerFactory.getLogger(OrderRefundController.class);

    @Autowired
    private OrderRefundService orderRefundService;


    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private OrderRefundAddrService orderRefundAddrService;


    @GetMapping("/userPage")
    @Operation(summary = "用户退款订单搜索接口", description = "用户退款订单搜索接口")
    public ServerResponseEntity<PageVO<OrderRefundVO>> pcPage(@Valid PageDTO pageDTO, OrderRefundSearchDTO orderRefundSearchDTO) {
        PageVO<OrderRefundVO> orderRefundPage = orderRefundService.userOrderRefundPage(pageDTO, orderRefundSearchDTO);
        return ServerResponseEntity.success(orderRefundPage);
    }

    @PostMapping("/apply")
    @Operation(summary = "申请退款", description = "申请退款")
    public ServerResponseEntity<Long> apply(@Valid @RequestBody OrderRefundDTO orderRefundParam) {
        Long userId = AuthUserContext.get().getUserId();
        // 获取订单信息
        Order order = orderService.getOrderByOrderIdAndUserId(orderRefundParam.getOrderId(), userId);

        // 商品是否已经发货
        boolean isDelivered = Objects.equals(order.getStatus(), OrderStatus.CONSIGNMENT.value()) || Objects.equals(order.getStatus(), OrderStatus.SUCCESS.value());

        ServerResponseEntity<Long> checkOrderStatusResponse = checkOrderStatus(orderRefundParam, order, isDelivered);
        if (!checkOrderStatusResponse.isSuccess()) {
            LOGGER.error("申请退款失败，原因：{}", checkOrderStatusResponse.getMsg());
            return checkOrderStatusResponse;
        }

        // 生成退款单信息
        OrderRefund newOrderRefund = new OrderRefund();
        newOrderRefund.setPaySysType(order.getPaySysType());
        // 获取所有正在进行中的退款订单
        List<OrderRefund> orderRefunds = orderRefundService.getProcessOrderRefundByOrderId(order.getOrderId());

        for (OrderRefund orderRefund : orderRefunds) {
            if (Objects.equals(RefundType.ALL.value(), orderRefund.getRefundType())) {
                LOGGER.error("申请退款失败，原因：{}", "该订单正在进行整单退款，无法进行新的退款操作");
                return ServerResponseEntity.showFailMsg("该订单正在进行整单退款或者正在进行平台介入中，无法进行新的退款操作");
            }
            if (Objects.equals(orderRefund.getOrderItemId(), orderRefundParam.getOrderItemId())) {
                LOGGER.error("申请退款失败，原因：{}", "该商品正在进行退款中，无法进行新的退款操作");
                return ServerResponseEntity.showFailMsg("该商品正在进行退款或者正在进行平台介入中，无法进行新的退款操作");
            }
        }

        // 如果存在分销订单，则计算分销总金额
        List<OrderItem> orderItemList = orderItemService.listOrderItemsByOrderId(order.getOrderId());
        // 判断退款单类型（1:整单退款,2:单个物品退款）
        if (orderRefundParam.getRefundType().equals(RefundType.ALL.value())) {
            LOGGER.info("申请整单退款，订单号：{}", order.getOrderId());
            // 全部物品退款
            // 计算该订单项的分销金额
            newOrderRefund.setDistributionTotalAmount(orderService.sumTotalDistributionAmountByOrderItem(orderItemList));
            // 计算平台退款金额（退款时将这部分钱退回给平台，所以商家要扣除从平台这里获取的金额）
            newOrderRefund.setPlatformRefundAmount(order.getPlatformAmount());
            newOrderRefund.setPlatformRefundCommission(order.getPlatformCommission());
            newOrderRefund.setRefundActualTotal(order.getActualTotal());
            newOrderRefund.setPurchaseRefundAmount(orderItemList.stream().mapToLong(OrderItem::getItemPurchaseAmount).sum());
            newOrderRefund.setPurPlatformRefundCommission(orderItemList.stream().mapToLong(OrderItem::getPurchasePlatformCommission).sum());
        } else {
            if (Objects.nonNull(orderRefundParam.getGiveawayItemIds())){
                RedisUtil.set(OrderCacheNames.REFUND_GIVEAWAY_ORDER_ITEM + orderRefundParam.getOrderItemId(), orderRefundParam.getGiveawayItemIds(), 3600);
            }
            LOGGER.info("申请单个物品退款，订单号：{}", order.getOrderId());
            ServerResponseEntity<Long> doItemRefundResponse = doItemRefund(orderRefundParam, order, isDelivered, newOrderRefund, orderRefunds, orderItemList);
            if (!doItemRefundResponse.isSuccess()) {
                LOGGER.error("申请退款失败，原因：{}", doItemRefundResponse.getMsg());
                return doItemRefundResponse;
            }
        }
        newOrderRefund.setSupplierId(0L);
        // 判断下是否为供应商订单,如果是商家代销供应商商品且为供应商发货设置供应商信息
        if (!Objects.equals(order.getSupplierId(), 0L) && Objects.equals(order.getSupplierDeliveryType(), 1)) {
            LOGGER.info("申请退款，订单号：{}，为供应商订单", order.getOrderId());
            newOrderRefund.setSupplierId(order.getSupplierId());
        }
        newOrderRefund.setShopId(order.getShopId());
        newOrderRefund.setUserId(order.getUserId());
        newOrderRefund.setOrderId(order.getOrderId());
        newOrderRefund.setRefundType(orderRefundParam.getRefundType());

        newOrderRefund.setRefundAmount(orderRefundParam.getRefundAmount());
        if (Objects.equals(RefundType.ALL.value(), orderRefundParam.getRefundType())) {
            newOrderRefund.setOrderItemId(0L);
            newOrderRefund.setRefundCount(order.getAllCount());
        } else {
            newOrderRefund.setOrderItemId(orderRefundParam.getOrderItemId());
            newOrderRefund.setRefundCount(orderRefundParam.getRefundCount() + orderRefundParam.getGiveawayRefundCount());
        }
        newOrderRefund.setApplyType(orderRefundParam.getApplyType());
        if (Objects.equals(orderRefundParam.getApplyType(), RefundApplyType.REFUND_AND_RETURNS.value())) {
            LOGGER.info("申请退款，订单号：{}，申请类型：退货退款", order.getOrderId());
            newOrderRefund.setIsReceived(1);
        } else {
            newOrderRefund.setIsReceived(orderRefundParam.getIsReceived());
        }
        newOrderRefund.setBuyerReason(orderRefundParam.getBuyerReason());
        newOrderRefund.setBuyerDesc(orderRefundParam.getBuyerDesc());
        newOrderRefund.setBuyerMobile(orderRefundParam.getBuyerMobile());
        newOrderRefund.setImgUrls(orderRefundParam.getImgUrls());
        newOrderRefund.setReturnMoneySts(ReturnProcessStatusEnum.APPLY.value());
        newOrderRefund.setUpdateTime(new Date());
        orderRefundService.applyRefund(newOrderRefund);
        return ServerResponseEntity.success(newOrderRefund.getRefundId());
    }

    /**
     * 用户提交物流公司信息
     */
    @PostMapping("/submit_express")
    @Operation(summary = "提交退款订单物流填写信息", description = "提交退款订单物流填写信息")
    public ServerResponseEntity<Void> submitExpress(@Valid @RequestBody OrderRefundDeliveryDTO orderRefundExpressParam) {
        OrderRefundVO orderRefundVO = orderRefundService.getByRefundId(orderRefundExpressParam.getRefundId());
        if (Objects.isNull(orderRefundVO)) {
            // 查询不到退款信息
            return ServerResponseEntity.showFailMsg("退款订单不存在");
        }

        Long userId = AuthUserContext.get().getUserId();
        if (!Objects.equals(orderRefundVO.getUserId(), userId)) {
            return ServerResponseEntity.fail(ResponseEnum.UNAUTHORIZED);
        }

        if (!Objects.equals(orderRefundVO.getApplyType(), RefundApplyType.REFUND_AND_RETURNS.value())) {
            // 当前申请类型不允许提交物流信息操作
            return ServerResponseEntity.showFailMsg("当前申请类型不允许提交物流信息操作");
        }
        if (!Objects.equals(orderRefundVO.getReturnMoneySts(), ReturnProcessStatusEnum.PROCESSING.value())
                && !Objects.equals(orderRefundVO.getReturnMoneySts(), ReturnProcessStatusEnum.CONSIGNMENT.value())) {
            // 当前状态不允许提交物流信息操作
            return ServerResponseEntity.showFailMsg("当前状态不允许提交物流信息操作");
        }

        // 填写物流信息 申请退货的时候已经有退货信息了
        OrderRefundAddr orderRefundAddr = orderRefundAddrService.getByRefundId(orderRefundExpressParam.getRefundId());
        orderRefundAddr.setSenderMobile(orderRefundExpressParam.getMobile());
        orderRefundAddr.setSenderRemarks(orderRefundExpressParam.getSenderRemarks());
        orderRefundAddr.setDeliveryCompanyId(orderRefundExpressParam.getDeliveryCompanyId());
        orderRefundAddr.setDeliveryName(orderRefundExpressParam.getDeliveryName());
        orderRefundAddr.setDeliveryNo(orderRefundExpressParam.getDeliveryNo());
        orderRefundAddr.setImgs(orderRefundExpressParam.getImgs());
        orderRefundAddr.setCreateTime(new Date());

        OrderRefund orderRefund = BeanUtil.map(orderRefundVO, OrderRefund.class);
        orderRefundService.submitExpress(orderRefund, orderRefundAddr);
        // 提交成功
        return ServerResponseEntity.success();
    }


    /**
     * 用户撤销退货退款申请
     */
    @PutMapping("/cancel")
    @Operation(summary = "撤销退货退款申请")
    public ServerResponseEntity<Void> cancel(@RequestBody Long refundId) {
        OrderRefundVO orderRefundVO = orderRefundService.getByRefundId(refundId);
        if (Objects.isNull(orderRefundVO)) {
            // 撤销失败 退款订单不存在
            return ServerResponseEntity.showFailMsg("退款订单不存在");
        }
        if (Objects.equals(orderRefundVO.getReturnMoneySts(), ReturnProcessStatusEnum.PROCESSING.value())) {
            // 卖家正在处理退款，不能撤销退款申请
            return ServerResponseEntity.showFailMsg("卖家正在处理退款，不能撤销退款申请");
        }
        if (Objects.equals(orderRefundVO.getReturnMoneySts(), ReturnProcessStatusEnum.CONSIGNMENT.value())) {
            // 买家已发货，不能撤销退款申请
            return ServerResponseEntity.showFailMsg("买家已发货，不能撤销退款申请");
        }
        if (Objects.equals(orderRefundVO.getReturnMoneySts(), ReturnProcessStatusEnum.RECEIVE.value())) {
            // 卖家已收货，不能撤销退款申请
            return ServerResponseEntity.showFailMsg("卖家已收货，不能撤销退款申请");
        }
        if (Objects.equals(orderRefundVO.getReturnMoneySts(), ReturnProcessStatusEnum.SUCCESS.value())) {
            return ServerResponseEntity.showFailMsg("退款已成功，不能撤销退款申请");
        }
        Long userId = AuthUserContext.get().getUserId();

        // 查看订单是否还有处于处理中的退款单，如果没有则修改订单退款状态为关闭状态
        Order order = orderService.getOrderByOrderIdAndUserId(orderRefundVO.getOrderId(), userId);

        //如果订单状态为待发货、包含运费、单个商品退款，且所有订单项都进行退款，则不能再取消退款（取消退款后再退款会导致重复退运费bug）
        if (Objects.equals(order.getStatus(), OrderStatus.PAYED.value()) && Objects.equals(orderRefundVO.getRefundType(), RefundType.SINGLE.value())
                && order.getFreightAmount() - order.getPlatformFreeFreightAmount() > 0) {
            // 退款数量
            int refundCount = orderRefundService.countByReturnMoneyStsAndOrderId(1, 6, order.getOrderId());
            // 订单项数量
            int orderItemCount = orderItemService.countByOrderId(order.getOrderId());
            if (refundCount == orderItemCount) {
                // 该订单所有商品都进行退款，已无法取消退款
                return ServerResponseEntity.showFailMsg("该订单所有商品都进行退款，已无法取消退款");
            }
        }

        if (Objects.equals(orderRefundVO.getReturnMoneySts(), ReturnProcessStatusEnum.SUCCESS.value()) ||
                Objects.equals(orderRefundVO.getReturnMoneySts(), ReturnProcessStatusEnum.FAIL.value())) {
            // 撤销失败 当前状态不允许此操作
            return ServerResponseEntity.showFailMsg("撤销失败 当前状态不允许此操作");
        }

        orderRefundService.cancelRefund(orderRefundVO);


        return ServerResponseEntity.success();
    }

    /**
     * 用户申请平台介入
     */
    @PutMapping("/apply_platform_intervention")
    @Operation(summary = "用户发起/修改平台申请介入")
    public ServerResponseEntity<Void> applyPlatormIntervertion(@RequestBody OrderRefundInterventionDTO orderRefundParam) {
        OrderRefundVO orderRefundVO = orderRefundService.getByRefundId(orderRefundParam.getRefundId());
        if (Objects.isNull(orderRefundVO)) {
            // 退款订单不存在
            return ServerResponseEntity.showFailMsg("退款订单不存在");
        }
        if (Objects.equals(orderRefundVO.getReturnMoneySts(), ReturnProcessStatusEnum.SUCCESS.value())) {
            // 买家已发货，不能申请平台介入
            return ServerResponseEntity.showFailMsg("退款已经成功，不能申请平台介入");
        }
        if (!Objects.equals(orderRefundVO.getReturnMoneySts(), ReturnProcessStatusEnum.FAIL.value())) {
            // 卖家正在处理退款，不能申请平台介入
            return ServerResponseEntity.showFailMsg("卖家正在处理退款，不能申请平台介入");
        }
        if (Objects.equals(orderRefundVO.getPlatformInterventionStatus(),PlatformInterventionStatus.AGREE.value())
                || Objects.equals(orderRefundVO.getPlatformInterventionStatus(), PlatformInterventionStatus.SUCCESS.value())
                || Objects.equals(orderRefundVO.getPlatformInterventionStatus(), PlatformInterventionStatus.REJECT.value())) {
            // 平台介入状态异常，不能申请平台介入
            return ServerResponseEntity.showFailMsg("平台介入状态异常，不能申请平台介入");
        }
        Date updateOutTime = DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), -4)).toJdkDate();
        if (Objects.equals(orderRefundVO.getPlatformInterventionStatus(),PlatformInterventionStatus.APPLY.value())
                && DateUtil.compare(orderRefundVO.getApplyInterventionTime(),updateOutTime) < 0) {
            // 平台介入状态异常，不能申请平台介入
            return ServerResponseEntity.showFailMsg("已过用户修改时间不能继续修改申请");
        }
        // 判断一下有没有过维权期，如果订单已经确认收货，且在15天维权期内则可以申请
        Long userId = AuthUserContext.get().getUserId();

        // 查看订单是否还有处于处理中的退款单，如果没有则修改订单退款状态为关闭状态
        Order order = orderService.getOrderByOrderIdAndUserId(orderRefundVO.getOrderId(), userId);
        if(Objects.equals(order.getStatus(),OrderStatus.SUCCESS.value())){
            Date finallyTime = DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), -15)).toJdkDate();
            if(DateUtil.compare(order.getFinallyTime(),finallyTime) < 0){
                throw new LuckException("已过维权期，不可以申请平台介入");
            }
        }
        if(!Objects.equals(order.getStatus(),OrderStatus.PAYED.value())) {
            // 不是待发货状态,可能是待发货前申请,发货完在进行平台介入,所以判断一下最大可退金额
            long canRefundAmount = order.getActualTotal() - order.getFreightAmount() + order.getPlatformFreeFreightAmount();
            if (orderRefundVO.getRefundAmount() > canRefundAmount) {
                throw new LuckException("订单状态变动,请重新发起退款申请");
            }
        }
        // 订单项或者整单订单有正在退款或者正在平台介入的时候,不能申请平台介入
        List<OrderRefundVO> processingOrderRefunds = orderRefundService.getProcessingOrderRefundByOrderId(orderRefundVO.getOrderId());
        List<OrderRefundVO> filterOrderRefunds = processingOrderRefunds.stream().filter(orderRefund -> Objects.equals(orderRefund.getOrderItemId(), 0L) || Objects.equals(orderRefund.getOrderItemId(), orderRefundVO.getOrderItemId())).toList();
        if(CollectionUtil.isNotEmpty(filterOrderRefunds)){
            throw new LuckException("订单正在申请退款或者正在平台介入中,不能申请平台介入");
        }
        orderRefundService.applyPlatormIntervertion(orderRefundParam,orderRefundVO);

        return ServerResponseEntity.success();
    }

    /**
     * 用户撤销平台申请介入
     */
    @PutMapping("/cancel_platform_intervention")
    @Operation(summary = "用户撤销平台申请介入")
    public ServerResponseEntity<Void> cacelPlatormIntervertion(@RequestBody OrderRefundInterventionDTO orderRefundParam) {
        OrderRefundVO orderRefundVO = orderRefundService.getByRefundId(orderRefundParam.getRefundId());
        if (Objects.isNull(orderRefundVO)) {
            // 退款订单不存在
            return ServerResponseEntity.showFailMsg("退款订单不存在");
        }
        if (Objects.equals(orderRefundVO.getReturnMoneySts(), ReturnProcessStatusEnum.SUCCESS.value())) {
            return ServerResponseEntity.showFailMsg("退款已经成功，无需撤销平台申请介入");
        }
        if (!Objects.equals(orderRefundVO.getPlatformInterventionStatus(), PlatformInterventionStatus.APPLY.value())) {
            return ServerResponseEntity.showFailMsg("当前申请介入状态异常，不能撤销平台介入");
        }
        // 判断一下有没有过维权期，如果订单已经确认收货，且在15天维权期内则可以申请
        Long userId = AuthUserContext.get().getUserId();

        // 查看订单是否还有处于处理中的退款单，如果没有则修改订单退款状态为关闭状态
        Order order = orderService.getOrderByOrderIdAndUserId(orderRefundVO.getOrderId(), userId);
        if(Objects.equals(order.getStatus(),OrderStatus.SUCCESS.value())){
            Date finallyTime = DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), -15)).toJdkDate();
            if(DateUtil.compare(order.getFinallyTime(),finallyTime) < 0){
                throw new LuckException("已过维权期，不可以撤销平台介入，建议联系平台客服");
            }
        }
        orderRefundService.cacelPlatormIntervertion(orderRefundParam,orderRefundVO);

        return ServerResponseEntity.success();
    }

    /**
     * 查看退款订单详情
     */
    @GetMapping("/info")
    @Operation(summary = "查看退款订单详情", description = "查看退款订单详情")
    public ServerResponseEntity<OrderRefundVO> info(Long refundId) {
        // 查询详情
        OrderRefundVO orderRefundVO = orderRefundService.getDetailByRefundId(refundId);
        int giveawayCount = 0;
        for (RefundOrderItemVO orderItem : orderRefundVO.getOrderItems()) {
            if(CollectionUtil.isNotEmpty(orderItem.getGiveawayList())) {
                giveawayCount += orderItem.getGiveawayList().stream().mapToInt(RefundOrderItemVO::getCount).sum();
            }
        }
        orderRefundVO.setRefundCount(orderRefundVO.getRefundCount() - giveawayCount);
        if (orderRefundVO == null) {
            // 查看失败 该退款订单不存在
            return ServerResponseEntity.showFailMsg("该退款订单不存在");
        }

        if (!Objects.equals(orderRefundVO.getUserId(), AuthUserContext.get().getUserId())) {
            // 查看失败 您没有此权限
            return ServerResponseEntity.fail(ResponseEnum.UNAUTHORIZED);
        }
        // 退货地址
        if (Objects.equals(orderRefundVO.getApplyType(), RefundApplyType.REFUND_AND_RETURNS.value()) && orderRefundVO.getHandelTime() != null) {
            OrderRefundAddr orderRefundAddr = orderRefundAddrService.getByRefundId(refundId);
            orderRefundVO.setOrderRefundAddr(BeanUtil.map(orderRefundAddr, OrderRefundAddrVO.class));
        }
        return ServerResponseEntity.success(orderRefundVO);
    }

    /**
     * 修改退款订单详情
     */
    @PutMapping("/update_refund")
    @Operation(summary = "修改退款订单详情", description = "修改退款订单详情，仅在用户申请平台介入后可以修改")
    public ServerResponseEntity<Long> updateRefund(@RequestBody OrderRefundDTO orderRefundParam) {
        OrderRefundVO orderRefundVO = orderRefundService.getByRefundId(orderRefundParam.getRefundId());
        Long userId = AuthUserContext.get().getUserId();
        if (Objects.isNull(orderRefundVO)) {
            // 退款订单不存在
            return ServerResponseEntity.showFailMsg("退款订单不存在");
        }
        if (Objects.equals(orderRefundVO.getReturnMoneySts(), ReturnProcessStatusEnum.SUCCESS.value())) {
            // 买家已发货，不能申请平台介入
            return ServerResponseEntity.showFailMsg("退款已经成功，不能申请平台介入");
        }
        if (!Objects.equals(orderRefundVO.getReturnMoneySts(), ReturnProcessStatusEnum.FAIL.value())) {
            // 卖家正在处理退款，不能申请平台介入
            return ServerResponseEntity.showFailMsg("卖家正在处理退款，不能申请平台介入");
        }
        if (!Objects.equals(orderRefundVO.getPlatformInterventionStatus(),PlatformInterventionStatus.APPLY.value())){
            // 平台介入状态异常，不能申请平台介入
            return ServerResponseEntity.showFailMsg("平台介入状态异常，不能修改退款信息");
        }
        // 获取订单信息
        Order order = orderService.getOrderByOrderIdAndUserId(orderRefundParam.getOrderId(), userId);
        OrderRefund orderRefund = new OrderRefund();
        orderRefund.setRefundAmount(orderRefundParam.getRefundAmount());
        orderRefund.setRefundId(orderRefundParam.getRefundId());
        orderRefund.setImgUrls(orderRefundParam.getImgUrls());
        orderRefund.setBuyerDesc(orderRefundParam.getBuyerDesc());
        orderRefund.setApplyType(orderRefundParam.getApplyType());
        orderRefund.setBuyerMobile(orderRefundParam.getBuyerMobile());
        orderRefund.setBuyerReason(orderRefundParam.getBuyerReason());
        orderRefund.setRefundType(orderRefundParam.getRefundType());
        // 商品是否已经发货
        boolean isDelivered = Objects.equals(order.getStatus(), OrderStatus.CONSIGNMENT.value()) || Objects.equals(order.getStatus(), OrderStatus.SUCCESS.value());
        if (Objects.equals(RefundType.ALL.value(), orderRefundParam.getRefundType())) {
            orderRefund.setOrderItemId(0L);
            orderRefund.setRefundCount(order.getAllCount());
        } else {
            ServerResponseEntity<Long> doItemRefundResponse = doItemRefund(orderRefundParam, order, isDelivered, orderRefund, null, null);
            if (!doItemRefundResponse.isSuccess()) {
                LOGGER.error("申请退款失败，原因：{}", doItemRefundResponse.getMsg());
                return doItemRefundResponse;
            }
            // 部分物品退款
            OrderItemVO orderItemVO = orderItemService.getByOrderItemId(orderRefundParam.getOrderItemId());
            // 退款物品数量为null或者0时，则为退款全部数量
            if (orderRefundParam.getRefundCount() <= 0) {
                orderRefundParam.setRefundCount(orderItemVO.getCount());
            }
            orderRefund.setOrderItemId(orderRefundParam.getOrderItemId());
            orderRefund.setRefundCount(orderRefundParam.getRefundCount() + orderRefundParam.getGiveawayRefundCount());
        }
        orderRefund.setRefundCount(orderRefundParam.getRefundCount());
        if (Objects.equals(orderRefundParam.getApplyType(), RefundApplyType.REFUND_AND_RETURNS.value())) {
            orderRefund.setIsReceived(1);
        } else {
            orderRefund.setIsReceived(orderRefundParam.getIsReceived());
        }
        orderRefund.setUpdateTime(new Date());
        orderRefundService.update(orderRefund);
        return ServerResponseEntity.success();
    }


    /**
     * TODO 测试用途
     */
    @PutMapping("/test_update_refund_time")
    @Operation(summary = "", description = "")
    public ServerResponseEntity<Void> testUpdateRefundTime(@RequestBody OrderRefundDTO orderRefundParam) {
        OrderRefundVO orderRefundVO = orderRefundService.getByRefundId(orderRefundParam.getRefundId());
        OrderRefund orderRefund = new OrderRefund();
        orderRefund.setRefundId(orderRefundParam.getRefundId());
        orderRefund.setApplyInterventionTime(DateUtil.offsetDay(orderRefundVO.getApplyInterventionTime(),-4));
        orderRefundService.update(orderRefund);
        return ServerResponseEntity.success();
    }

    /**
     * 查看我的退款订单列表
     */
    @GetMapping("/page")
    @Operation(summary = "我的退款订单列表", description = "我的退款订单列表，显示数量时候")
    public ServerResponseEntity<EsPageVO<EsOrderRefundVO>> list(PageDTO page, OrderRefundSearchDTO orderRefundPageDTO) {
        orderRefundPageDTO.setUserId(AuthUserContext.get().getUserId());
        EsPageVO<EsOrderRefundVO> pageList = orderRefundService.page(page, orderRefundPageDTO);
        return ServerResponseEntity.success(pageList);
    }

    private ServerResponseEntity<Long> doItemRefund(OrderRefundDTO orderRefundParam, Order order, boolean isDelivered, OrderRefund newOrderRefund, List<OrderRefund> orderRefunds, List<OrderItem> orderItemList) {
        // 部分物品退款
        OrderItemVO orderItemVO = orderItemService.getByOrderItemId(orderRefundParam.getOrderItemId());
        if (orderItemVO == null) {
            // 该物品在订单中不存在
            return ServerResponseEntity.fail(ResponseEnum.ORDER_NOT_EXIST);
        }
        if (!isCanRefund(orderItemList)) {
            // 该订单部分订单项支付金额和积分为0，无法使用部分退款
            return ServerResponseEntity.showFailMsg("该订单部分订单项支付金额和积分为0，无法使用部分退款");
        }
        if (Objects.equals(orderItemVO.getSpuMold(), 1) && Objects.equals(orderRefundParam.getApplyType(), RefundApplyType.REFUND_AND_RETURNS.value())) {
            return ServerResponseEntity.showFailMsg("虚拟商品只能选择仅退款");
        }
        // 用户实际能退的运费 = 订单当前运费 - 平台减免运费
        long freightAmount = order.getFreightAmount() - order.getPlatformFreeFreightAmount();
        //赠品处理
        long itemActualTotal = orderItemVO.getActualTotal();
        long giveawayRefundAmount = 0;
        StringBuilder returnGiveawayIds = new StringBuilder(Constant.INITIAL_CAPACITY);
        // 赠品处理
        giveawayRefundAmount = handleGiveawayProd(orderRefundParam, newOrderRefund, orderItemVO, giveawayRefundAmount, returnGiveawayIds);
        // 最多可以退的实付金额需要减去不退回的赠品退款金额,最小值应该为0.01，理论上赠品价值不可能大于商品
        itemActualTotal = (long) Arith.sub(itemActualTotal, giveawayRefundAmount);
        // 计算该订单项的分销金额
        OrderItem tempOrderItem = BeanUtil.map(orderItemVO, OrderItem.class);
        newOrderRefund.setDistributionTotalAmount(orderService.sumTotalDistributionAmountByOrderItem(Collections.singletonList(tempOrderItem)));

        handlePlatformAmount(orderRefundParam, newOrderRefund, orderItemVO, itemActualTotal);
        // 采购金额应退 = 采购金额 *（退款金额 / 实付金额）
        Long purchaseRefundAmount = PriceUtil.divideByBankerRounding(orderItemVO.getItemPurchaseAmount() * orderRefundParam.getRefundAmount(), itemActualTotal);
        // 积分全部抵扣的情况下，退款金额为0，实付金额也为0，此时采购金额应退订单采购金额
        if(itemActualTotal == 0 && orderRefundParam.getRefundAmount() == 0) {
            purchaseRefundAmount = orderItemVO.getItemPurchaseAmount();
        }
        newOrderRefund.setPurchaseRefundAmount(purchaseRefundAmount);

        newOrderRefund.setRefundActualTotal(itemActualTotal);

        // 退款物品数量为null或者0时，则为退款全部数量
        if (orderRefundParam.getRefundCount() <= 0) {
            orderRefundParam.setRefundCount(orderItemVO.getCount());
        }

        // 判断退款数量是否溢出
        if (orderRefundParam.getRefundCount() > orderItemVO.getCount()) {
            // 退款物品数量已超出订单中的数量，不允许申请
            return ServerResponseEntity.showFailMsg("退款物品数量已超出订单中的数量，不允许申请");
        }

        // 判断退款金额是否超出订单金额3种情况
        double refundSingleAmount = Arith.div(Arith.add(orderRefundParam.getRefundAmount(), giveawayRefundAmount), orderRefundParam.getRefundCount(), 3);
        refundSingleAmount = Arith.sub(refundSingleAmount, giveawayRefundAmount);

        // 单件退款金额
        double singleAmount = Arith.div(orderItemVO.getActualTotal(), orderItemVO.getCount(), 3);

        // 可以退款的实际金额应该为 当前退款数量 * singleAmount(单个最大退款金额) - 赠品金额,并且不能超过订单项的实付金额
        double productTotalAmount = orderItemVO.getSpuTotalAmount() + orderItemVO.getShopChangeFreeAmount() - giveawayRefundAmount;
        // 2.如果不是直接跟订单项进行判断
        if (refundSingleAmount > productTotalAmount || refundSingleAmount > singleAmount) {
            // 退款金额已超出订单金额，无法申请
            return ServerResponseEntity.showFailMsg("退款金额已超出订单金额，无法申请");
        }
        // 3.当前退款金额  +  已申请退款金额 > 订单实际支付总额， 就不能退款了
        double refundAmount = orderRefundParam.getRefundAmount();
        if(CollectionUtil.isEmpty(orderRefunds)){
            return ServerResponseEntity.success();
        }
        // 已退款总金额
        double alreadyRefundTotal = orderRefunds.stream().mapToDouble(OrderRefund::getRefundAmount).sum();
        if (Arith.add(refundAmount, alreadyRefundTotal) > order.getActualTotal()) {
            // 退款金额已超出订单金额，无法申请
            return ServerResponseEntity.showFailMsg("退款金额已超出订单金额，无法申请");
        }
        // 一个订单项只能申请一次退款
        for (OrderRefund orderRefund : orderRefunds) {
            if (Objects.equals(orderRefund.getOrderItemId(), orderItemVO.getOrderItemId())) {
                // 退款订单项已处理，请勿重复申请
                return ServerResponseEntity.showFailMsg("退款订单项已处理，请勿重复申请");
            }
        }
        return ServerResponseEntity.success();
    }

    private static boolean isCanRefund(List<OrderItem> orderItemList) {
        boolean isCanRefund = true;
        if(CollectionUtil.isEmpty(orderItemList)){
            return isCanRefund;
        }
        //  查看是否有支付金额和积分都为空的订单，有则抛出异常
        for (OrderItem item : orderItemList) {
            if (!Objects.equals(item.getActivityType(), OrderActivityType.GIVEAWAY.value()) && !Objects.equals(item.getActivityType(), OrderActivityType.COMBO_PROD.value())) {
                if (item.getActualTotal() <= 0 && item.getUseScore() <= 0) {
                    isCanRefund = false;
                    break;
                }
            }
        }
        return isCanRefund;
    }

    private static void handlePlatformAmount(OrderRefundDTO orderRefundParam, OrderRefund newOrderRefund, OrderItemVO orderItemVO, long itemActualTotal) {
        // 计算平台退款金额（退款时将这部分钱退回给平台，所以商家要扣除从平台这里获取的金额）
        Long changePlatformAmount;
        // 平台佣金应退 = 平台佣金 *（退款金额 / 实付金额）
        Long changePlatformCommission;
        if (orderRefundParam.getRefundAmount() != itemActualTotal && orderRefundParam.getRefundAmount() != 0) {
            // 平台退款金额 = 平台优惠金额 *（退款金额 / 实付金额）
            changePlatformAmount = PriceUtil.divideByBankerRounding(orderItemVO.getPlatformShareReduce() * orderRefundParam.getRefundAmount(), itemActualTotal);
            changePlatformCommission = PriceUtil.divideByBankerRounding(orderItemVO.getPlatformCommission() * orderRefundParam.getRefundAmount(), itemActualTotal);
        } else {
            changePlatformAmount = orderItemVO.getPlatformShareReduce();
            changePlatformCommission = orderItemVO.getPlatformCommission();
        }
        // 此处设置实际平台抵现金额
        newOrderRefund.setPlatformRefundAmount(changePlatformAmount);

        newOrderRefund.setPlatformRefundCommission(changePlatformCommission);

        // 平台供应商佣金应退 = 平台供应商佣金 *（退款金额 / 实付金额）
        // 退款金额为0时，是纯积分退款，金额无法修改，直接从商品中取佣金
        Long changeSupplierPlatformCommission;
        if (orderRefundParam.getRefundAmount() == 0L) {
            changeSupplierPlatformCommission = orderItemVO.getPurchasePlatformCommission();
        } else {
            changeSupplierPlatformCommission = PriceUtil.divideByBankerRounding(orderItemVO.getPurchasePlatformCommission() * orderRefundParam.getRefundAmount(), itemActualTotal);
        }

        newOrderRefund.setPurPlatformRefundCommission(changeSupplierPlatformCommission);
    }

    private long handleGiveawayProd(OrderRefundDTO orderRefundParam, OrderRefund newOrderRefund, OrderItemVO orderItem, long giveawayRefundAmount, StringBuilder returnGiveawayIds) {
        // 判断是否为赠品的主商品--活动类型为赠品，且活动id等于0
        int giveawayCount = 0;
        if (Objects.equals(orderItem.getMainGiveaway(), 1)) {
            boolean isReturnGiveaway = true;
            List<OrderItemVO> giveawayItemList = orderItemService.getOrderItemByGiveawayOrderItemId(orderItem.getUserId(), orderItem.getOrderItemId());
            List<Long> giveawayItemIds = orderRefundParam.getGiveawayItemIds();
            for (OrderItemVO giveawayItem : giveawayItemList) {
                if (giveawayItemIds.contains(giveawayItem.getOrderItemId())) {
                    returnGiveawayIds.append(giveawayItem.getOrderItemId()).append(StrUtil.COMMA);
                    giveawayCount += giveawayItem.getCount();
                    continue;
                }
                isReturnGiveaway = false;
                // 不退回判断金额
                giveawayRefundAmount = (long) Arith.add(giveawayRefundAmount, giveawayItem.getGiveawayAmount());
            }
            // 如果是全部退回则不需要判断退款金额
            if (isReturnGiveaway) {
                giveawayRefundAmount = 0;
            }
        }
        if (returnGiveawayIds.length() > 0) {
            returnGiveawayIds.deleteCharAt(returnGiveawayIds.length() - 1);
            newOrderRefund.setReturnGiveawayIds(returnGiveawayIds.toString());
        } else {
            newOrderRefund.setReturnGiveawayIds(null);
        }
        orderRefundParam.setGiveawayRefundCount(giveawayCount);
        return giveawayRefundAmount;
    }


    private ServerResponseEntity<Long> checkOrderStatus(OrderRefundDTO orderRefundParam, Order order, boolean isDelivered) {
        //待收货或者确认收货 -> 整单退款 -> 退款金额 < 订单金额 - 运费金额
        if (isDelivered && orderRefundParam.getRefundType().equals(RefundType.ALL.value())) {
            long refundAmount = order.getActualTotal() - (order.getFreightAmount() - order.getPlatformFreeFreightAmount());
            if (Math.abs(orderRefundParam.getRefundAmount()) > refundAmount) {
                // 退款金额已超出订单金额，无法申请
                return ServerResponseEntity.showFailMsg("退款金额已超出订单金额");
            }
        }

        if (!Objects.equals(order.getIsPayed(), 1)) {
            // 当前订单还未付款，无法申请
            return ServerResponseEntity.showFailMsg("当前订单还未付款，无法申请退款");
        }

        if (Objects.equals(order.getStatus(), OrderStatus.CLOSE.value())) {
            // 当前订单已失败，不允许退款
            return ServerResponseEntity.showFailMsg("当前订单已关闭");
        }

        if (Objects.equals(order.getStatus(), OrderStatus.WAIT_GROUP.value())) {
            // 当前订单正在等待成团状态，需等待成团才能进行下一步操作
            return ServerResponseEntity.showFailMsg("当前订单正在等待成团状态，需等待成团才能进行下一步操作");
        }

        if (Objects.equals(order.getStatus(), OrderStatus.WAIT_BALANCE.value())) {
            // 当前订单正在等待支付尾款状态，需完成支付尾款才能进行下一步操作
            return ServerResponseEntity.showFailMsg("当前订单正在等待支付尾款状态，需完成支付尾款才能进行下一步操作");
        }


        if (orderRefundParam.getRefundAmount() > order.getActualTotal()) {
            return ServerResponseEntity.showFailMsg("退款金额已超出订单金额，无法申请");
        }


        if (!orderRefundService.checkRefundDate(order)) {
            return ServerResponseEntity.showFailMsg("当前订单已超过可退款时间，无法退款");
        }
        if (Objects.equals(order.getOrderType(), OrderType.SCORE.value())) {
            //
            return ServerResponseEntity.showFailMsg("积分商品，无法退款");
        }

        boolean hasRefund = !Objects.isNull(order.getRefundStatus()) && !Objects.equals(order.getRefundStatus(), RefundStatusEnum.DISAGREE.value());
        if (Objects.equals(orderRefundParam.getRefundType(), RefundType.ALL.value()) && hasRefund) {
            // 该订单已有商品正在退款中，不能再进行整单退款
            return ServerResponseEntity.showFailMsg("该订单已有商品正在退款中，不能再进行整单退款");
        }

        if (order.getOrderMold() == 1 && order.getWriteOffNum() == -1 && order.getWriteOffMultipleCount() == -1 && order.getWriteOffCount() > 0) {
            // 该订单已有商品核销，无法退款
            return ServerResponseEntity.showFailMsg("该订单已有商品核销，无法退款");
        }
        return ServerResponseEntity.success();
    }

}
