package com.yami.shop.api.controller;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.app.dto.ApiOrderRefundDto;
import com.yami.shop.bean.app.param.OrderRefundExpressParam;
import com.yami.shop.bean.app.param.OrderRefundParam;
import com.yami.shop.bean.dto.OrderRefundDto;
import com.yami.shop.bean.enums.OrderStatus;
import com.yami.shop.bean.enums.RefundStatusEnum;
import com.yami.shop.bean.enums.RefundType;
import com.yami.shop.bean.enums.ReturnMoneyStsType;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.param.OrderDto;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.exception.GlobalException;
import com.yami.shop.common.util.Arith;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.common.util.RefundSnUtils;
import com.yami.shop.dao.OrderItemMapper;
import com.yami.shop.dao.OrderRefundRecordMapper;
import com.yami.shop.dao.OrderRefundSkuMapper;
import com.yami.shop.dao.PointsRecordMapper;
import com.yami.shop.delivery.comment.api.paotui.PaoTuiApi;
import com.yami.shop.delivery.comment.api.paotui.model.request.AddWithoutShopRequest;
import com.yami.shop.delivery.comment.api.paotui.model.request.DeliveryCpriceRequest;
import com.yami.shop.delivery.comment.api.paotui.model.request.OrderDetailRequest;
import com.yami.shop.delivery.comment.api.paotui.model.response.DeliveryPriceResponse;
import com.yami.shop.delivery.comment.api.paotui.model.response.OrderResponse;
import com.yami.shop.delivery.comment.api.paotui.model.response.OrderStatusResponse;
import com.yami.shop.delivery.comment.service.TransportManagerService;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.*;
import com.yami.shop.utils.CullenUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Slf4j
@RestController
@RequestMapping("/p/orderRefund")
//@RequestMapping("/orderRefund")
@Api(tags = "订单退款接口")
@AllArgsConstructor
public class OrderRefundController {

    private final OrderRefundService orderRefundService;

    private final OrderRefundRecordMapper orderRefundRecordMapper;

    private final OrderRefundSkuMapper orderRefundSkuMapper;

    private final OrderService orderService;

    private final MapperFacade mapperFacade;

    private final OrderItemService orderItemService;

    private final RefundDeliveryService refundDeliveryService;

    private final ShopDetailService shopDetailService;

    private final UserAddrService userAddrService;

    @Autowired
    private OrderItemMapper orderItemMapper;


    private final TransportManagerService transportManagerService;

    @Autowired
    private PaoTuiApi paoTuiApi;

    @Autowired
    private IQnhService qnhService;

    @Autowired
    private UserAddrOrderService userAddrOrderService;

    @Autowired
    private UserService userService;

    @Autowired
    private SkuService skuService;

    @Autowired
    PointsRecordMapper pointsRecordMapper;


    @GetMapping("getIsDistribution")
    @ApiOperation(value = "获取是否在配送中")
    public ResponseEntity<Boolean> getIsDistribution(String orderNumber) {
        Order order = orderService.getOrderByOrderNumber(orderNumber);
        if (ObjectUtil.isEmpty(order)) {
            throw new GlobalException("订单编号不存在，订单编号是否正确");
        }
        // 已支付订单取消订单，已付款后需要相应处理物流状态
        OrderDetailRequest orderDetailRequest = new OrderDetailRequest();
        orderDetailRequest.setOrder_id(order.getDvyFlowId());
        orderDetailRequest.setOrigin_id(orderNumber);
        try {
            OrderStatusResponse orderStatusResponse = paoTuiApi.deliveryRoute(orderDetailRequest);
            if (ObjectUtil.isNotEmpty(orderStatusResponse.getInfo()) && orderStatusResponse.getInfo().size() > 0) {
                if (orderStatusResponse.getInfo().get(0).getStatus() == 40) {
                    return ResponseEntity.ok(true);
                }
            }
            return ResponseEntity.ok(false);
        } catch (Exception e) {
            return ResponseEntity.ok(false);
        }
    }


    @PostMapping("/applyAgain")
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation(value = "申请退款(再次提交)", notes = "申请退款(再次提交)")
    public synchronized ResponseEntity<String> applyAgain(@Valid @RequestBody OrderRefundParam orderRefundParam) {
        log.info("小程序(再次提交)申请退款参数:{}", JSONObject.toJSONString(orderRefundParam));
        Long refundId = orderRefundParam.getRefundId();
        CullenUtils.validateDataThrowException(refundId == null, "请输入旧退款订单ID...");
        List<OrderRefundSku> orderRefundSkuList = orderRefundParam.getOrderRefundSkuList();
        CullenUtils.validateDataThrowException(orderRefundSkuList.isEmpty(), "退款商品不能为空...");
        String userId = SecurityUtils.getUser().getUserId();
        // 获取订单信息
        Order order = orderService.getOrderByOrderNumberAndUserId(orderRefundParam.getOrderNumber(), userId, true);

        if (!Objects.equals(order.getIsPayed(), 1)) {
            throw new GlobalException("当前订单还未付款，无法申请");
        }

        if (Objects.equals(order.getHbOrderStatus(), OrderStatus.CLOSE.value())) {
            throw new GlobalException("当前订单已失败，不允许退款");
        }

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

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

        if (!orderRefundService.checkRefundDate(order)) {
            throw new GlobalException("当前订单已确认收货超过" + Constant.MAX_FINALLY_REFUND_TIME + "天，无法退款");
        }

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

        // 生成退款单信息
        OrderRefund newOrderRefund = new OrderRefund();

        // 获取所有正在进行中的退款订单
        List<OrderRefund> orderRefunds = orderRefundService.getProcessingOrderRefundByOrderId(order.getOrderId());

        // 如果存在分销订单，则计算分销总金额
        List<OrderItem> orderItemList = orderItemService.getOrderItemsByOrderNumber(order.getOrderNumber());
        // 判断退款单类型（1:整单退款,2:单个物品退款）
        if (orderRefundParam.getRefundType().equals(RefundType.ALL.value())) {
            // 全部物品退款
            // 计算该订单项的分销金额
            newOrderRefund.setDistributionTotalAmount(orderService.sumTotalDistributionAmountByOrderItem(orderItemList));
            // 计算平台退款金额（退款时将这部分钱退回给平台，所以商家要扣除从平台这里获取的金额）
            newOrderRefund.setPlatformRefundAmount(order.getPlatformAmount());
        }

        newOrderRefund.setShopId(order.getShopId());
        newOrderRefund.setUserId(order.getUserId());
        newOrderRefund.setOrderId(order.getOrderId());
        newOrderRefund.setOrderNumber(order.getOrderNumber());
        newOrderRefund.setRefundSn(RefundSnUtils.generate());
        newOrderRefund.setRefundType(orderRefundParam.getRefundType());

        newOrderRefund.setRefundAmount(orderRefundParam.getRefundAmount());
        if (Objects.equals(RefundType.ALL.value(), orderRefundParam.getRefundType())) {
            newOrderRefund.setOrderItemId(0L);
        } else {
            newOrderRefund.setOrderItemId(orderRefundParam.getOrderItemId());
            // 待发货状态-最后一件商品进行退款，退款金额 =  商品金额 + 订单运费金额
            if (Objects.equals(order.getHbOrderStatus(), OrderStatus.PADYED.value()) && order.getFreightAmount() > 0) {
                int orderItenCount = orderItemService.count(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderNumber, order.getOrderNumber()));
                if (Objects.equals(orderRefunds.size(), orderItenCount - 1)) {
                    newOrderRefund.setRefundAmount(Arith.add(newOrderRefund.getRefundAmount(), order.getFreightAmount()));
                }
            }
        }

        newOrderRefund.setGoodsNum(orderRefundParam.getGoodsNum());
        newOrderRefund.setApplyType(orderRefundParam.getApplyType());
        if (Objects.equals(orderRefundParam.getApplyType(), 2)) {
            newOrderRefund.setIsReceiver(true);
        } else {
            newOrderRefund.setIsReceiver(orderRefundParam.getIsReceiver());
        }
        newOrderRefund.setBuyerReason(orderRefundParam.getBuyerReason());
        newOrderRefund.setBuyerDesc(orderRefundParam.getBuyerDesc());
        newOrderRefund.setBuyerMobile(orderRefundParam.getBuyerMobile());
        newOrderRefund.setPhotoFiles(orderRefundParam.getPhotoFiles());
        newOrderRefund.setReturnMoneySts(ReturnMoneyStsType.APPLY.value());
        newOrderRefund.setFreightAmount(orderRefundParam.getFreightAmount());
        newOrderRefund.setApplyTime(new Date());
        newOrderRefund.setUpdateTime(new Date());

        long orderPoints = order.getOffsetPoints() == null ? 0 : order.getOffsetPoints();
        if (orderPoints == 0) {
            newOrderRefund.setOffsetPoints(orderPoints);
        } else {
            double refundTotalPoints = orderRefundParam.getOrderRefundSkuList().stream()
                    .mapToDouble(item -> item.getSkuPrice() * item.getProductCount())
                    .sum() * 100;
            long refundPoints = Math.round(refundTotalPoints);
            newOrderRefund.setOffsetPoints(Math.min(refundPoints, orderPoints));
        }

        OrderRefund orderRefund = orderRefundService.applyRefund(newOrderRefund);
        if (!orderRefundSkuList.isEmpty()) {
            orderRefundSkuList.forEach(c -> {
                c.setOrderRefundId(orderRefund.getRefundId());
                orderRefundSkuMapper.insert(c);
            });
        }

        //生成退款记录
        addOrderRefundRecord(orderRefund.getRefundId(), 1, 1, newOrderRefund.getBuyerReason());

        //生成待商家审核记录
        addOrderRefundRecord(orderRefund.getRefundId(), 2, 2, "你的服务单已申请成功，待商家审核");

        orderRefundService.removeById(refundId);
        orderRefundSkuMapper.delete(new LambdaQueryWrapper<OrderRefundSku>().eq(OrderRefundSku::getOrderRefundId, refundId));

        //创建海博退款单
        log.info("创建海博退款单，生成海博退款单信息{}", orderRefund);
        orderRefundService.createRefundOrder(orderRefund.getOrderNumber(), orderRefund.getRefundSn());
        return ResponseEntity.ok(newOrderRefund.getRefundSn());
    }


    @PostMapping("/apply")
    @ApiOperation(value = "申请退款", notes = "申请退款")
    public ResponseEntity<String> apply(@Valid @RequestBody OrderRefundParam orderRefundParam) {
        log.info("小程序申请退款参数:{}", JSONObject.toJSONString(orderRefundParam));
        List<OrderRefundSku> orderRefundSkuList = orderRefundParam.getOrderRefundSkuList();
        CullenUtils.validateDataThrowException(orderRefundSkuList.isEmpty(), "退款商品不能为空...");
        String userId = SecurityUtils.getUser().getUserId();
//        String userId = "36726893042d492aba446439c5f00584";
        // 获取订单信息
        Order order = orderService.getOrderByOrderNumberAndUserId(orderRefundParam.getOrderNumber(), userId, true);

        if (!Objects.equals(order.getIsPayed(), 1)) {
            throw new GlobalException("当前订单还未付款，无法申请");
        }

        if (Objects.equals(order.getHbOrderStatus(), OrderStatus.CLOSE.value())) {
            throw new GlobalException("当前订单已失败，不允许退款");
        }

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

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

        if (!orderRefundService.checkRefundDate(order)) {
            throw new GlobalException("当前订单已确认收货超过" + Constant.MAX_FINALLY_REFUND_TIME + "天，无法退款");
        }

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

        List<Integer> returnMoneySts = new ArrayList<>();
        returnMoneySts.add(ReturnMoneyStsType.APPLY.value());
        returnMoneySts.add(ReturnMoneyStsType.PROCESSING.value());
        returnMoneySts.add(ReturnMoneyStsType.CONSIGNMENT.value());
        returnMoneySts.add(ReturnMoneyStsType.RECEIVE.value());
        int count = orderRefundService.count(new LambdaQueryWrapper<OrderRefund>()
                .eq(OrderRefund::getOrderId, order.getOrderId())
                .in(OrderRefund::getReturnMoneySts, returnMoneySts));

        log.info("已存在退款订单数量{}", count);
        if (count > 0) {
            // 处理已存在退款的情况
            throw new GlobalException("该订单已有退款正在进行中");
        }

        // 生成退款单信息
        OrderRefund newOrderRefund = new OrderRefund();

        // 获取所有正在进行中的退款订单
        List<OrderRefund> orderRefunds = orderRefundService.getProcessingOrderRefundByOrderId(order.getOrderId());

        for (OrderRefund orderRefund : orderRefunds) {
            if (Objects.equals(RefundType.ALL.value(), orderRefund.getRefundType())) {
                throw new GlobalException("该订单正在进行整单退款，无法进行新的退款操作");
            }
            if (Objects.equals(orderRefund.getOrderItemId(), orderRefundParam.getOrderItemId())) {
                throw new GlobalException("该商品正在进行退款中，无法进行新的退款操作");
            }
        }

        // 如果存在分销订单，则计算分销总金额
        List<OrderItem> orderItemList = orderItemService.getOrderItemsByOrderNumber(order.getOrderNumber());
        // 判断退款单类型（1:整单退款,2:单个物品退款）
        if (orderRefundParam.getRefundType().equals(RefundType.ALL.value())) {
            // 全部物品退款
            // 计算该订单项的分销金额
            newOrderRefund.setDistributionTotalAmount(orderService.sumTotalDistributionAmountByOrderItem(orderItemList));
            // 计算平台退款金额（退款时将这部分钱退回给平台，所以商家要扣除从平台这里获取的金额）
            newOrderRefund.setPlatformRefundAmount(order.getPlatformAmount());
        }

        newOrderRefund.setShopId(order.getShopId());
        newOrderRefund.setUserId(order.getUserId());
        newOrderRefund.setOrderId(order.getOrderId());
        newOrderRefund.setOrderNumber(order.getOrderNumber());
        newOrderRefund.setRefundSn(RefundSnUtils.generate());
        newOrderRefund.setRefundType(orderRefundParam.getRefundType());

        newOrderRefund.setRefundAmount(orderRefundParam.getRefundAmount());
        if (Objects.equals(RefundType.ALL.value(), orderRefundParam.getRefundType())) {
            newOrderRefund.setOrderItemId(0L);
        } else {
            newOrderRefund.setOrderItemId(orderRefundParam.getOrderItemId());
            // 待发货状态-最后一件商品进行退款，退款金额 =  商品金额 + 订单运费金额
            if (Objects.equals(order.getHbOrderStatus(), OrderStatus.PADYED.value()) && order.getFreightAmount() > 0) {
                int orderItenCount = orderItemService.count(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderNumber, order.getOrderNumber()));
                if (Objects.equals(orderRefunds.size(), orderItenCount - 1)) {
                    newOrderRefund.setRefundAmount(Arith.add(newOrderRefund.getRefundAmount(), order.getFreightAmount()));
                }
            }
        }
        BigDecimal refundTotalMoney=BigDecimal.ZERO;
        for (OrderRefundSku orderRefundSku : orderRefundSkuList) {
            int mul = (int) Arith.mul(orderRefundSku.getSkuPrice(), 100)*orderRefundSku.getProductCount();
            refundTotalMoney= refundTotalMoney.add(BigDecimal.valueOf(mul));
        }
        //计算退款订单金额 整单退款需要退运费
        if (orderRefundParam.getRefundType().equals(RefundType.ALL.value())){
            refundTotalMoney= refundTotalMoney.add(BigDecimal.valueOf(Arith.mul(order.getFreightAmount(), 100)));
        }

        newOrderRefund.setRefundTotalMoney(BigDecimal.valueOf(Arith.div(refundTotalMoney.doubleValue(), 100,2)));
        newOrderRefund.setGoodsNum(orderRefundParam.getGoodsNum());
        newOrderRefund.setApplyType(orderRefundParam.getApplyType());
        if (Objects.equals(orderRefundParam.getApplyType(), 2)) {
            newOrderRefund.setIsReceiver(true);
        } else {
            newOrderRefund.setIsReceiver(orderRefundParam.getIsReceiver());
        }
        newOrderRefund.setBuyerReason(orderRefundParam.getBuyerReason());
        newOrderRefund.setBuyerDesc(orderRefundParam.getBuyerDesc());
        newOrderRefund.setBuyerMobile(orderRefundParam.getBuyerMobile());
        newOrderRefund.setPhotoFiles(orderRefundParam.getPhotoFiles());
        newOrderRefund.setReturnMoneySts(ReturnMoneyStsType.APPLY.value());
        newOrderRefund.setApplyTime(new Date());
        newOrderRefund.setUpdateTime(new Date());
        newOrderRefund.setFreightAmount(orderRefundParam.getFreightAmount());

        long orderPoints = order.getOffsetPoints() == null ? 0 : order.getOffsetPoints();
        if (orderPoints == 0) {
            newOrderRefund.setOffsetPoints(orderPoints);
        } else {
            double refundTotalPoints = orderRefundParam.getOrderRefundSkuList().stream()
                    .mapToDouble(item -> item.getSkuPrice() * item.getProductCount())
                    .sum() * 100;
            long refundPoints = Math.round(refundTotalPoints);
            newOrderRefund.setOffsetPoints(Math.min(refundPoints, orderPoints));
        }
        //需要再这里调用获取过期积分和退款积分
//        getExpiredAndReturn(newOrderRefund,order,orderRefundSkuList);
        OrderRefund orderRefund = orderRefundService.applyRefund(newOrderRefund);
        if (!orderRefundSkuList.isEmpty()) {
            orderRefundSkuList.forEach(c -> {
                c.setOrderRefundId(orderRefund.getRefundId());
                orderRefundSkuMapper.insert(c);
            });
        }

        //生成退款记录
        addOrderRefundRecord(orderRefund.getRefundId(), 1, 1, newOrderRefund.getBuyerReason());

        //生成待商家审核记录
        addOrderRefundRecord(orderRefund.getRefundId(), 2, 2, "你的服务单已申请成功，待商家审核");

        //创建海博退款单
        log.info("创建海博退款单，生成海博退款单信息{}", orderRefund);
        orderRefundService.createRefundOrder(orderRefund.getOrderNumber(), orderRefund.getRefundSn());

        return ResponseEntity.ok(newOrderRefund.getRefundSn());
    }

    /**
     * 计算配送价格
     */
    @GetMapping("/refundPrice")
    @ApiOperation(value = "计算配送价格", notes = "")
    public ResponseEntity<RefundDelivery> refundPrice(String refundSn, Long deliveryTime) {

        OrderRefund orderRefund = orderRefundService.getOrderRefundByRefundSn(refundSn);
        String userId = SecurityUtils.getUser().getUserId();
        // 获取订单信息
        Order order = orderService.getById(orderRefund.getOrderId());

        // 退货信息
        RefundDelivery refundDelivery = refundDeliveryService.getOne(new LambdaQueryWrapper<RefundDelivery>()
                .eq(RefundDelivery::getRefundSn, refundSn));

        UserAddr userAddrByUserId = userAddrService.getUserAddrByUserId(order.getAddrOrderId(), userId);
        if (ObjectUtil.isEmpty(userAddrByUserId)) {
            userAddrByUserId = userAddrService.getUserAddrByUserId(0L, userId);
        }
        ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(orderRefund.getShopId());


        Double trans = transportManagerService.calculateTransfeeSecond2(shopDetail.getShopId(), userAddrByUserId);

        refundDelivery.setPrice(trans);
        refundDelivery.setTouchTime(System.currentTimeMillis());
        refundDelivery.setDeliveryTime(deliveryTime);
        refundDeliveryService.update(refundDelivery, new LambdaQueryWrapper<RefundDelivery>()
                .eq(RefundDelivery::getRefundSn, refundSn));
        return ResponseEntity.ok(refundDelivery);
    }

    /**
     * 用户提交物流公司信息
     */
    @GetMapping("/submitExpress/{refundSn}")
    @ApiOperation(value = "提交退款订单物流填写信息", notes = "")
    public ResponseEntity<String> submitExpress(@PathVariable("refundSn") String refundSn) {
        OrderRefund orderRefund = orderRefundService.getOrderRefundByRefundSn(refundSn);
        if (Objects.isNull(orderRefund)) {
            throw new GlobalException("查询不到退款信息");
        }

        String userId = SecurityUtils.getUser().getUserId();
        if (!Objects.equals(orderRefund.getUserId(), userId)) {
            throw new GlobalException("申请失败，您没有该权限");
        }

        if (!Objects.equals(orderRefund.getApplyType(), 2)) {
            throw new GlobalException("当前申请类型不允许提交物流信息操作");
        }

        if (!Objects.equals(orderRefund.getReturnMoneySts(), ReturnMoneyStsType.PROCESSING.value())) {
            throw new GlobalException("当前状态不允许提交物流信息操作");
        }

        RefundDelivery refundDelivery = refundDeliveryService.getOne(new LambdaQueryWrapper<RefundDelivery>()
                .eq(RefundDelivery::getRefundSn, refundSn));

        if (refundDelivery.getPayer().equals("2") && !refundDelivery.isPay()) {
            throw new GlobalException("未支付退货费用");
        }
        Order order = orderService.getById(orderRefund.getOrderId());
        UserAddr userAddrOrder = userAddrService.getUserAddrByUserId(order.getAddrOrderId(), userId);
        if (ObjectUtil.isEmpty(userAddrOrder)) {
            userAddrOrder = userAddrService.getUserAddrByUserId(0L, userId);
        }
        ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(orderRefund.getShopId());

        // 计算价格
        DeliveryCpriceRequest deliveryCpriceRequest = new DeliveryCpriceRequest();
        deliveryCpriceRequest.setReceiver_longitude(shopDetail.getShopLng());
        deliveryCpriceRequest.setReceiver_latitude(shopDetail.getShopLat());
        deliveryCpriceRequest.setReceiver_address(shopDetail.getProvince() + shopDetail.getCity() + shopDetail.getArea() + shopDetail.getShopAddress());
        deliveryCpriceRequest.setReceiver_name(refundDelivery.getReceiverName());
        deliveryCpriceRequest.setReceiver_phone(refundDelivery.getReceiverMobile());
        deliveryCpriceRequest.setSender_longitude(String.valueOf(userAddrOrder.getLongitude()));
        deliveryCpriceRequest.setSender_latitude(String.valueOf(userAddrOrder.getLatitude()));
        deliveryCpriceRequest.setSender_address(userAddrOrder.getAddress() + userAddrOrder.getAddressName() + userAddrOrder.getAddrDetail());
        deliveryCpriceRequest.setCity(shopDetail.getCityId());
        deliveryCpriceRequest.setSenderPhone(userAddrOrder.getMobile());
        deliveryCpriceRequest.setSenderName(userAddrOrder.getReceiver());
        deliveryCpriceRequest.setGoods_weight(1);
        deliveryCpriceRequest.setGoods_category(5);
        deliveryCpriceRequest.setDelivery_time(refundDelivery.getDeliveryTime());
        deliveryCpriceRequest.setMap_type(1);
        DeliveryPriceResponse deliveryPriceResponse = paoTuiApi.ordercPrice(deliveryCpriceRequest);

        // 发货
        AddWithoutShopRequest addOrderRequest = new AddWithoutShopRequest();
        addOrderRequest.setShop_id(deliveryPriceResponse.getShop_origin_id());
        addOrderRequest.setShop_name("退货配送");
        addOrderRequest.setOrigin_id(refundSn);
        addOrderRequest.setIs_subscribe(1);
        addOrderRequest.setSubscribe_time(refundDelivery.getDeliveryTime());
        addOrderRequest.setCity(shopDetail.getCityId());
        addOrderRequest.setSender_longitude(userAddrOrder.getLongitude());
        addOrderRequest.setSender_latitude(userAddrOrder.getLatitude());
        addOrderRequest.setSender_phone(userAddrOrder.getMobile());
        addOrderRequest.setSender_address(userAddrOrder.getAddress() + userAddrOrder.getAddressName() + userAddrOrder.getAddrDetail());
        addOrderRequest.setReceiver_longitude(shopDetail.getShopLng());
        addOrderRequest.setReceiver_latitude(shopDetail.getShopLat());
        addOrderRequest.setReceiver_address(shopDetail.getProvince() + shopDetail.getCity() + shopDetail.getArea() + shopDetail.getShopAddress());
        addOrderRequest.setReceiver_address_detail(shopDetail.getShopAddress());
        addOrderRequest.setReceiver_phone(refundDelivery.getReceiverMobile());
        addOrderRequest.setReceiver_name(refundDelivery.getReceiverName());


        OrderResponse orderResponse = paoTuiApi.orderaddWithoutShop(addOrderRequest);
        refundDelivery.setSenderMobile(userAddrOrder.getMobile());
//        refundDelivery.setSenderRemarks(orderRefundExpressParam.getSenderRemarks());
//        refundDelivery.setDeyId(orderRefundExpressParam.getExpressId());
        refundDelivery.setDeyName("聚合配送");
        refundDelivery.setDeyNu(orderResponse.getOrder_id());
//        refundDelivery.setImgs(orderRefundExpressParam.getImgs());
        refundDelivery.setCreateTime(new Date());

        // 更新退款单信息
        orderRefund.setReturnMoneySts(ReturnMoneyStsType.RECEIVE.value());
        orderRefund.setShipTime(new Date());
        orderRefund.setUpdateTime(new Date());

        orderRefundService.submitExpress(orderRefund, refundDelivery);


        //海博退款单状态同步65
        log.info("客户填写完成快递信息后海博退款单状态同步65");
        orderRefundService.changeStatus(orderRefund.getRefundSn(), ReturnMoneyStsType.RECEIVE.value());

        return ResponseEntity.ok("提交成功");
    }

    /**
     * 用户修改物流公司信息
     */
    @PutMapping("/reSubmitExpress")
    @ApiOperation(value = "修改退款订单物流填写信息", notes = "修改物流公司信息")
    public ResponseEntity<String> updateExpress(@Valid @RequestBody OrderRefundExpressParam orderRefundExpressParam) {
        String userId = SecurityUtils.getUser().getUserId();
        OrderRefund orderRefund = orderRefundService.getOrderRefundByRefundSn(orderRefundExpressParam.getRefundSn());
        if (Objects.isNull(orderRefund)) {
            throw new GlobalException("查询不到退款信息");
        }

        if (!Objects.equals(orderRefund.getUserId(), userId)) {
            throw new GlobalException("申请失败，您没有此权限");
        }

        if (!Objects.equals(orderRefund.getReturnMoneySts(), ReturnMoneyStsType.CONSIGNMENT.value())) {
            throw new GlobalException("当前状态不允许更新物流信息操作");
        }

        // 填写物流信息
        RefundDelivery refundDelivery = refundDeliveryService.getOne(new LambdaQueryWrapper<RefundDelivery>()
                .eq(RefundDelivery::getRefundSn, orderRefundExpressParam.getRefundSn()));
        refundDelivery.setSenderMobile(orderRefundExpressParam.getMobile());
        refundDelivery.setDeyId(orderRefundExpressParam.getExpressId());
        refundDelivery.setSenderRemarks(orderRefundExpressParam.getSenderRemarks());
        refundDelivery.setDeyNu(orderRefundExpressParam.getExpressNo());
        refundDelivery.setImgs(orderRefundExpressParam.getImgs());
        refundDelivery.setReceiverMobile(orderRefundExpressParam.getMobile());
        refundDelivery.setDeyName(orderRefundExpressParam.getExpressName());

        // 更新退款单信息
        orderRefund.setUpdateTime(new Date());

        orderRefundService.submitExpress(orderRefund, refundDelivery);
        return ResponseEntity.ok("修改成功");
    }

    /**
     * 用户撤销退货退款申请
     */
    @GetMapping("/cancel")
    @ApiOperation(value = "撤销退货退款申请", notes = "")
    public ResponseEntity<String> cancel(@RequestParam("refundSn") String refundSn) {
        OrderRefundDto orderRefund = orderRefundService.getOrderRefundByRefundSn(refundSn);
        if (Objects.isNull(orderRefund)) {
            throw new GlobalException("撤销失败 退款订单不存在");
        }
        if (Objects.equals(orderRefund.getReturnMoneySts(), ReturnMoneyStsType.PROCESSING.value())) {
            throw new GlobalException("卖家正在处理退款，不能撤销退款申请");
        }
        if (Objects.equals(orderRefund.getReturnMoneySts(), ReturnMoneyStsType.CONSIGNMENT.value())) {
            throw new GlobalException("买家已发货，不能撤销退款申请");
        }
        if (Objects.equals(orderRefund.getReturnMoneySts(), ReturnMoneyStsType.RECEIVE.value())) {
            throw new GlobalException("卖家已收货，不能撤销退款申请");
        }
        if (Objects.equals(orderRefund.getReturnMoneySts(), ReturnMoneyStsType.SUCCESS.value())) {
            throw new GlobalException("退款成功，不能撤销退款申请");
        }
        String userId = SecurityUtils.getUser().getUserId();

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

        //如果订单状态为待发货、包含运费、单个商品退款，且所有订单项都进行退款，则不能再取消退款（取消退款后再退款会导致重复退运费bug）
        if (Objects.equals(order.getHbOrderStatus(), OrderStatus.PADYED.value()) && Objects.equals(orderRefund.getRefundType(), 2) && order.getFreightAmount() > 0) {
            // 退款数量
            int refundCount = orderRefundService.count(new LambdaQueryWrapper<OrderRefund>()
                    .gt(OrderRefund::getReturnMoneySts, 0)
                    .lt(OrderRefund::getReturnMoneySts, 6)
                    .eq(OrderRefund::getOrderId, order.getOrderId())
            );
            // 订单项数量
            int orderItemCount = orderItemService.count(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderNumber, order.getOrderNumber()));
            if (refundCount == orderItemCount) {
                throw new GlobalException("该订单所有商品都进行退款，已无法取消退款");
            }
        }

        if (Objects.equals(orderRefund.getReturnMoneySts(), ReturnMoneyStsType.SUCCESS.value()) ||
                Objects.equals(orderRefund.getReturnMoneySts(), ReturnMoneyStsType.FAIL.value()) ||
                Objects.equals(orderRefund.getReturnMoneySts(), ReturnMoneyStsType.REJECT.value()) ||
                Objects.equals(orderRefund.getReturnMoneySts(), ReturnMoneyStsType.CANCEL.value())) {
            throw new GlobalException("撤销失败 当前状态不允许此操作");
        }

        Date now = new Date();
        orderRefund.setReturnMoneySts(ReturnMoneyStsType.CANCEL.value());
        //orderRefund.setReturnMoneySts(ReturnMoneyStsType.FAIL.value());
        orderRefund.setCancelTime(now);
        orderRefund.setUpdateTime(now);
        orderRefundService.updateById(orderRefund);


        List<OrderRefund> orderRefundList = orderRefundService.list(new LambdaQueryWrapper<OrderRefund>()
                .eq(OrderRefund::getOrderId, order.getOrderId()));
        long count = orderRefundList.stream().filter(item -> Objects.equals(item.getReturnMoneySts(), ReturnMoneyStsType.APPLY.value())
                || Objects.equals(item.getReturnMoneySts(), ReturnMoneyStsType.PROCESSING.value())
                || Objects.equals(item.getReturnMoneySts(), ReturnMoneyStsType.CONSIGNMENT.value())
                || Objects.equals(item.getReturnMoneySts(), ReturnMoneyStsType.RECEIVE.value())).count();
        if (count == 0) {
            order.setRefundStatus(RefundStatusEnum.DISAGREE.value());
            orderService.updateById(order);
        }
        orderRefundService.changeStatus(refundSn, 40);

        addOrderRefundRecord(orderRefund.getRefundId(), 4, 4, "用户主动撤回申请，退货退款关闭。");

        return ResponseEntity.ok("撤销成功");
    }


    /**
     * 查看退款订单详情
     */
    @GetMapping("/info")
    @ApiOperation(value = "查看退款订单详情", notes = "查看退款订单详情")
    public ResponseEntity<ApiOrderRefundDto> info(String refundSn) {
        // 查询详情
        OrderRefundDto orderRefundDto = orderRefundService.getOrderRefundByRefundSn(refundSn);
        if (orderRefundDto == null) {
            throw new GlobalException("查看失败 该退款订单不存在");
        }
        ApiOrderRefundDto apiOrderRefundDto = mapperFacade.map(orderRefundDto, ApiOrderRefundDto.class);
        if (apiOrderRefundDto.getMemberDiscountAmount() == null) {
            apiOrderRefundDto.setMemberDiscountAmount(0.0);
        }
        return ResponseEntity.ok(apiOrderRefundDto);
    }

    /**
     * 查看我的退款订单列表
     */
    @GetMapping("/list")
    @ApiOperation(value = "我的退款订单列表", notes = "我的退款订单列表，显示数量时候")
    @ApiImplicitParam(name = "applyType", value = "申请类型: 0/null 全部  1仅退款  2退款退货", required = false, dataType = "Integer")
    public ResponseEntity<IPage<ApiOrderRefundDto>> list(PageParam<OrderRefundDto> page,
                                                         @RequestParam(required = false) String startTime,
                                                         @RequestParam(required = false) String endTime,
                                                         @RequestParam(required = false) Integer applyType) {
        OrderRefundDto orderRefundDto = new OrderRefundDto();
        orderRefundDto.setUserId(SecurityUtils.getUser().getUserId());
        //orderRefundDto.setUserId("b7ab06c99e21450b848832d79aad773a");
        // 0/null全部  1仅退款 2退款退货
        if (Objects.equals(0, applyType)) {
            applyType = null;
        }
        orderRefundDto.setApplyType(applyType);
        IPage<OrderRefundDto> pageList = orderRefundService.getPage(page, orderRefundDto, startTime, endTime);

        // 克隆对象
        @SuppressWarnings("unchecked") IPage<ApiOrderRefundDto> apiPageList = mapperFacade.map(pageList, IPage.class);
        List<ApiOrderRefundDto> records = mapperFacade.mapAsList(pageList.getRecords(), ApiOrderRefundDto.class);
        records.forEach(item -> {
            if (item.getMemberDiscountAmount() == null) {
                item.setMemberDiscountAmount(0.0);
            }
        });
        apiPageList.setRecords(records);
        return ResponseEntity.ok(apiPageList);
    }

    /**
     * 创建牵牛花订单
     *
     * @param order
     * @return
     */
    public boolean createQNHOrder(Order order, String refundSn) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 待添加创建牵牛花订单
        OrderDto orderDto = new OrderDto();
        orderDto.setChannelSheetno(order.getOrderNumber());
        orderDto.setChannelKeyword("YYG");
        orderDto.setPayOver(true);
        orderDto.setBilltype("2");
        orderDto.setReturnOrderSn(refundSn);
        orderDto.setTotalSaleValue(BigDecimal.valueOf(order.getTotal()));
        orderDto.setTotalDiscValue(BigDecimal.ZERO);
        orderDto.setTotalSjDisc(BigDecimal.ZERO);
        orderDto.setTotalSaleValue(BigDecimal.ZERO);
        orderDto.setTotalPtDp(BigDecimal.ZERO);
        orderDto.setTotalSjDp(BigDecimal.ZERO);
        orderDto.setTotalPtDisc(BigDecimal.ZERO);
        orderDto.setCommissionValue(BigDecimal.ZERO);
        orderDto.setPayableValue(BigDecimal.valueOf(order.getTotal()));
        orderDto.setTotalItemValue(BigDecimal.valueOf(order.getTotal()));
        orderDto.setLogisticsModeKeyword(order.getFreightAmount().toString());


        ShopDetail shopDetailByShopId = shopDetailService.getById(order.getShopId());
        orderDto.setOrgCode(shopDetailByShopId.getThirdPartyCode());
        orderDto.setOrgName(shopDetailByShopId.getShopName());
        orderDto.setPreOrder(false);
        orderDto.setOfflineOrder(false);
        orderDto.setOrderTime(formatter.format(order.getCreateTime()));
        orderDto.setGroupId(0);
        orderDto.setGoodsReturn("true");
        UserAddrOrder addrOrder = userAddrOrderService.getById(order.getAddrOrderId());
        User user = userService.getUserByUserId(order.getUserId());

        //填充收件人信息
        orderDto.setReceiver(new OrderDto.Receiver());
        orderDto.getReceiver().setAddress(addrOrder.getAddress());
        orderDto.getReceiver().setMobile(user.getUserMobile());
        orderDto.getReceiver().setName(user.getNickName());
        orderDto.getReceiver().setType("0");
        orderDto.getReceiver().setLatitude(String.valueOf(addrOrder.getLatitude()));
        orderDto.getReceiver().setLongitude(String.valueOf(addrOrder.getLongitude()));
        orderDto.setPayableLogisticsValue(BigDecimal.valueOf(order.getPlatformAmount()));
        orderDto.setLogisticsModeKeyword("0");

        //填充买家信息
        orderDto.setBuyer(new OrderDto.Buyer());
        orderDto.getBuyer().setAddress(addrOrder.getAddress());
        orderDto.getBuyer().setNick(user.getNickName());
        orderDto.getBuyer().setEmail(user.getUserMail());
        orderDto.getBuyer().setNote(order.getRemarks());
        orderDto.getBuyer().setTel(user.getUserMobile());

        //填充支付信息
        orderDto.setOrderPayments(new OrderDto.OrderPayments());
        orderDto.getOrderPayments().setPayment(BigDecimal.valueOf(order.getTotal()));
        orderDto.getOrderPayments().setKeyword("10002");
        orderDto.getOrderPayments().setName("商城系统支付");
        ArrayList<OrderDto.OrderDetails> orderDetails = new ArrayList<>();
        int weight = 0;
        List<OrderItem> orderItems1 = orderItemService.getOrderItemsByOrderNumber(order.getOrderNumber());
        for (OrderItem orderItem : orderItems1) {
            OrderDto.OrderDetails orderDetails1 = new OrderDto.OrderDetails();
            Sku sku = skuService.getById(orderItem.getSkuId());
            orderDetails1.setSkuId(sku.getPartyCode());
            orderDetails1.setItemCode("");
            orderDetails1.setBarcode("");
            orderDetails1.setOrderItemId(orderItem.getOrderItemId().toString());
            orderDetails1.setName(orderItem.getProdName());
            orderDetails1.setOriginalPrice(BigDecimal.valueOf(sku.getOriPrice()));
            orderDetails1.setWeight((int) Math.round(sku.getWeight()));
            weight += orderDetails1.getWeight();
            orderDetails1.setSalePrice(BigDecimal.valueOf(sku.getPrice()));
            orderDetails1.setQty(orderItem.getProdCount());
            orderDetails1.setMoney(orderDetails1.getSalePrice().multiply(BigDecimal.valueOf(orderDetails1.getQty())));
            orderDetails.add(orderDetails1);
        }
        orderDto.setOrderDetails(orderDetails);
        orderDto.setWeight(weight);
        String added = qnhService.addOrder(orderDto);
        if (!StringUtils.isBlank(added)) {
            order.setQnhOrderId(added);
            order.setQnhOrderStatus("1");
            orderService.updateById(order);
            return true;
        }
        return false;
    }

    /**
     * 获取过期积分和退还积分
     * @param orderRefund
     * @param order
     * @param orderRefundSkuList
     */
    private void getExpiredAndReturn(OrderRefund orderRefund,Order order,List<OrderRefundSku> orderRefundSkuList){
        //退款的积分 将所有的钱都转为积分对比
        int totalRefundScore = 0;//需要退款的积分，部分退款时不需要退运费。
        //该未过期的积分
        long noRefundExpiredScore = 0L;
        //改订单总的积分
        long orderSumScore = 0L;

        int freightAmountScore = -(int) Arith.mul(order.getFreightAmount(), 100);//需要退的总积分,先把运费剔除掉
        for (OrderRefundSku orderRefundSku : orderRefundSkuList) {
            Integer productCount = orderRefundSku.getProductCount();
            OrderItem orderItem = orderItemMapper.selectById(orderRefundSku.getOrderItemId());
            totalRefundScore =  (int) (totalRefundScore+ Arith.mul(productCount * orderItem.getPrice(), 100));
        }
        if (orderRefund.getRefundType()==1){
            totalRefundScore+=freightAmountScore;
        }

        List<PointsRecord> pointsRecords = pointsRecordMapper.findByOrderNumber(order.getOrderNumber(), 2);
        for (PointsRecord pointsRecord : pointsRecords) {
            if (pointsRecord.getExpiryStatus()==1){
                int i=0;
                if (pointsRecord.getPointsAudit()==2){
                    i =pointsRecord.getVariablePoints().intValue();
                }else if(pointsRecord.getPointsAudit()==1){
                    i = pointsRecord.getPoints().intValue();
                }
                noRefundExpiredScore+=i;
            }
            if (pointsRecord.getPointsAudit()==2){
                orderSumScore +=pointsRecord.getVariablePoints().intValue();
            }else if(pointsRecord.getPointsAudit()==1){
                orderSumScore += pointsRecord.getPoints().intValue();
            }
        }
        if (order.getOffsetPoints()>0&&totalRefundScore!=0){
            if (order.getOffsetPoints()>=totalRefundScore){
                orderRefund.setOffsetPoints(Long.valueOf(totalRefundScore));
                if (totalRefundScore<=orderSumScore){
                    if (totalRefundScore>noRefundExpiredScore){
                        orderRefund.setRefundExpiredScore(totalRefundScore-noRefundExpiredScore);
                    }
                }
            }else {
                orderRefund.setOffsetPoints(order.getOffsetPoints());
                if (order.getOffsetPoints()<=orderSumScore){
                    if (order.getOffsetPoints()>noRefundExpiredScore){
                        orderRefund.setRefundExpiredScore(order.getOffsetPoints()-noRefundExpiredScore);
                    }
                }
            }
        }
    }

    private void addOrderRefundRecord(Long refundId, Integer auditStatus, Integer sort, String instructions) {
        OrderRefundRecord orderRefundRecord = new OrderRefundRecord();
        orderRefundRecord.setOrderRefundId(refundId);
        orderRefundRecord.setInstructions(instructions);
        Date date = new Date();
        orderRefundRecord.setCreateTime(date);
        orderRefundRecord.setUpdateTime(date);
        orderRefundRecord.setAuditStatus(auditStatus);
        orderRefundRecord.setSort(sort);
        orderRefundRecordMapper.insert(orderRefundRecord);
    }
}
