package com.yami.shop.multishop.controller;


import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil;
import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.yami.shop.bean.bo.RefundInfoBo;
import com.yami.shop.bean.dto.OrderRefundDto;
import com.yami.shop.bean.dto.RefundSnDto;
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.Order;
import com.yami.shop.bean.model.OrderItem;
import com.yami.shop.bean.model.OrderRefund;
import com.yami.shop.bean.param.CancelOrderParam;
import com.yami.shop.bean.param.OrderRefundParam;
import com.yami.shop.common.annotation.SysLog;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.enums.PayType;
import com.yami.shop.common.enums.YamiHttpStatus;
import com.yami.shop.common.exception.GlobalException;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.Arith;
import com.yami.shop.common.util.Json;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.delivery.comment.model.DeliveryOrder;
import com.yami.shop.delivery.comment.service.DeliveryOrderService;
import com.yami.shop.security.multishop.util.SecurityUtils;
import com.yami.shop.service.*;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.util.*;

@RestController
@AllArgsConstructor
@RequestMapping("/order/refund")
public class OrderRefundController {

    private final OrderRefundService orderRefundService;

    private final PayManagerService payManagerService;

    private final OrderItemService orderItemService;
    private final OrderService orderService;
    private final DeliveryOrderService deliveryOrderService;


    /**
     * 分页查询
     *
     * @param page           分页对象
     * @param orderRefundDto 实体对象
     * @return 分页数据
     */
    @GetMapping("/page")
    public ResponseEntity<IPage<OrderRefundDto>> getOrderRefundPage(PageParam<OrderRefundDto> page, OrderRefundDto orderRefundDto,
                                                                    @RequestParam(required = false) String startTime, @RequestParam(required = false) String endTime) {
        orderRefundDto.setShopId(SecurityUtils.getShopUser().getShopId());
        return ResponseEntity.ok(orderRefundService.getPage(page, orderRefundDto, startTime, endTime));
    }

    /**
     * 通过id查询
     *
     * @param refundId id
     * @return 查询详细信息
     */
    @GetMapping("/info/{refundId}")
    public ResponseEntity<OrderRefund> getById(@PathVariable("refundId") Long refundId) {
        OrderRefund orderRefund = orderRefundService.getOrderRefundById(refundId, SecurityUtils.getShopUser().getShopId());
        return ResponseEntity.ok(orderRefund);
    }

    /**
     * 进入这个方法，会出现两种情况：
     * 1. 仅退款，此时商家同意买家的退款申请，执行发放退款的操作
     * 2. 退货退款操作:
     * 2.1)退货退款的第一步，商家允许买家退款的申请，商家进行设置退货地址，不执行发放退款的操作
     * 2.2)退货退款的第二步，当商家收到货之后，同意买家退款，此时需要发放退款，但不会执行这个方法，执行的是下面这个方法
     *
     * @see com.yami.shop.multishop.controller.OrderRefundController#returnMoney(OrderRefundParam)
     */
    @SysLog("退款处理 -商家处理退款订单")
    @PutMapping("/process")
    public ResponseEntity<Void> processRefundOrder(@RequestBody OrderRefundParam orderRefundParam) {

        // 处理退款操作
        OrderRefundDto orderRefundDto = orderRefundService.processRefundOrder(orderRefundParam, SecurityUtils.getShopUser().getShopId());

        // 仅退款，执行退款操作
        if (Objects.equals(orderRefundDto.getApplyType(), 1)) {
            orderRefundService.submitWxRefund(orderRefundDto);
        }
        if (orderRefundDto.getReturnMoneySts() == 5) {
            // 将orderItem.status改成 0 表示可以发货
            OrderItem orderItem = orderItemService.getOne(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderItemId, orderRefundDto.getOrderItemId()));
            if (Objects.isNull(orderItem)) {
                return ResponseEntity.ok().build();
            }
            String orderNumber = orderItem.getOrderNumber();
            List<OrderItem> orderItems1 = orderItemService.list(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderNumber, orderNumber));
            if (orderItems1.size() <= 1) {
                return ResponseEntity.ok().build();
            }
            orderItemService.update(new LambdaUpdateWrapper<OrderItem>()
                    .set(OrderItem::getStatus, 0)
                    .eq(OrderItem::getOrderItemId, orderItem.getOrderItemId()));
            // 如果该单是商品项目的所有订单都是已发货，其他的都是退款成功，则可以改成订单项发货状态
            List<OrderItem> orderItems = orderItemService.list(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderNumber, orderNumber));
            // 如果所有的订单都是申请退款，并且退款成功，则不改变
            int total = 0;
            for (OrderItem item : orderItems) {
                int count = orderRefundService.count(new LambdaQueryWrapper<OrderRefund>()
                        .eq(OrderRefund::getOrderItemId, item.getOrderItemId())
                        .eq(OrderRefund::getReturnMoneySts, 5));
                if (count > 0) {
                    total++;
                }
            }
            // 所有订单都是退款成功
            if (total == orderItems.size()) {
                return ResponseEntity.ok().build();
            }
            boolean isOk = true;
            for (OrderItem item : orderItems) {
                if (item.getStatus() != 0) {
                    isOk = false;
                    break;
                }
            }
            // 所有的订单，有已发货的订单

            if (isOk) {
                Order order = new Order();
                order.setOrderId(orderRefundDto.getOrderId());
                // 更新到发货状态
                Date date = new Date();
                order.setHbOrderStatus(OrderStatus.CONSIGNMENT.value());
                order.setUpdateTime(date);
                order.setDvyTime(date);
                Integer type = null;
                for (OrderItem item : orderItems) {
                    if (Objects.nonNull(item.getDvyType())) {
                        type = item.getDvyType();
                    }
                }
                List<DeliveryOrder> deliveryOrders = deliveryOrderService.list(new LambdaQueryWrapper<DeliveryOrder>().eq(DeliveryOrder::getOrderNumber, orderNumber));
                if (!CollectionUtils.isEmpty(deliveryOrders)) {
                    order.setDvyType(1);
                } else {
                    order.setDvyType(type);
                }
                orderService.updateById(order);
            }

        }
        return ResponseEntity.ok().build();
    }

    /**
     * 退货处理
     */
    @SysLog("退款处理 -商家退货处理")
    @PutMapping("/returnMoney")
    public ResponseEntity<Void> returnMoney(@RequestBody OrderRefundParam orderRefundParam) {
        if (Objects.isNull(orderRefundParam.getIsReceiver())) {
            throw new GlobalException("退货状态不能为空");
        }
        // 退货处理
        OrderRefundDto orderRefundDto = orderRefundService.returnMoney(orderRefundParam, SecurityUtils.getShopUser().getShopId());
        // 执行退款操作
        orderRefundService.submitWxRefund(orderRefundDto);
        return ResponseEntity.ok().build();
    }

    /**
     * 退款请求（发放退款）
     */
    @SysLog("退款处理-发放退款")
    @PutMapping("/refundRequest")
    public void refundRequest(@RequestBody RefundSnDto refundSn) {
        // 获取退款信息
        OrderRefundDto orderRefundDto = orderRefundService.getOrderRefundByRefundSn(refundSn.getRefundSn());

        if (orderRefundDto == null) {
            throw new GlobalException("退款单不存在");
        }

        if (orderRefundDto.getDecisionTime() == null) {
            throw new GlobalException("请先确定退款，才能发起退款操作");
        }

        if (orderRefundDto.getRefundTime() != null) {
            throw new GlobalException("已退款成功，无法再申请退款操作");
        }
        if (!Objects.equals(orderRefundDto.getShopId(), SecurityUtils.getShopUser().getShopId())) {
            throw new GlobalException("未授权");
        }
        if (Objects.equals(-1, orderRefundDto.getReturnMoneySts())) {
            throw new GlobalException("买家已取消申请");
        }
        // 提交退款请求
        orderRefundService.submitWxRefund(orderRefundDto);
    }

    /**
     * 退款结果通知
     */
    @RequestMapping("/result/{payType}")
    public ResponseEntity<String> result(HttpServletRequest request, @RequestBody(required = false) String xmlData, @PathVariable Integer payType) throws WxPayException, UnsupportedEncodingException, AlipayApiException {

        RefundInfoBo refundInfo = payManagerService.validateAndGetRefundInfo(request, PayType.instance(payType), xmlData);
        if (refundInfo.getIsRefundSuccess()) {
            // 查询退款订单，验证退款信息
            OrderRefundDto orderRefundDto = orderRefundService.getOrderRefundByRefundSn(refundInfo.getRefundNo());
            orderRefundService.verifyRefund(orderRefundDto, refundInfo.getBizRefundNo());
        }
        return ResponseEntity.ok(refundInfo.getSuccessString());
    }


}
