/*
 * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.multishop.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.enums.*;
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.model.UserAddrOrder;
import com.yami.shop.bean.param.CancelOrderParam;
import com.yami.shop.bean.param.DeliveryOrderParam;
import com.yami.shop.bean.param.OrderParam;
import com.yami.shop.common.annotation.SysLog;
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.security.multishop.util.SecurityUtils;
import com.yami.shop.service.*;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author lgh on 2018/09/15.
 */
@Controller
@RequestMapping("/order/order")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private UserAddrOrderService userAddrOrderService;

    @Autowired
    private ProductService productService;

    @Autowired
    private SkuService skuService;

    @Autowired
    private OrderRefundService orderRefundService;

    @Autowired
    private  Snowflake snowflake;

    /**
     * 分页获取
     */
    @GetMapping("/page")
    public ResponseEntity<IPage<Order>> page(OrderParam orderParam,PageParam<Order> page) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        orderParam.setShopId(shopId);
        IPage<Order> orderIPage = orderService.pageOrdersDetialByOrderParam(page, orderParam);
        return ResponseEntity.ok(orderIPage);
    }

    /**
     * 获取信息
     */
    @GetMapping("/orderInfo/{orderNumber}")
    public ResponseEntity<Order> info(@PathVariable("orderNumber") String orderNumber) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        Order order = orderService.getOrderByOrderNumberAndShopId(orderNumber,shopId,true);
        List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber);
        order.setOrderItems(orderItems);
//        UserAddrOrder userAddrOrder = userAddrOrderService.getById(order.getAddrOrderId());
        UserAddrOrder userAddrOrder = userAddrOrderService.selectByAddrOrderId(order.getAddrOrderId());
        System.out.println(JSONUtil.toJsonStr(userAddrOrder));
        order.setUserAddrOrder(userAddrOrder);
        return ResponseEntity.ok(order);
    }

    /**
     * 发货
     */
    @PutMapping("/delivery")
    public ResponseEntity<Void> delivery(@RequestBody DeliveryOrderParam deliveryOrderParam) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        Order order = orderService.getOrderByOrderNumberAndShopId(deliveryOrderParam.getOrderNumber(),shopId,true);
        if (!Objects.equals(order.getHbOrderStatus(), OrderStatus.PADYED.value()) && Objects.equals(order.getDvyType(), DvyType.FETCH.value())){
            throw new GlobalException("订单不处于待入库状态，无法进行入库");
        }else if (!Objects.equals(order.getHbOrderStatus(), OrderStatus.PADYED.value())){
            throw new GlobalException("订单不处于待发货状态，无法进行发货");
        }
        List<OrderRefund> orderRefunds = orderRefundService.getProcessingOrderRefundByOrderId(order.getOrderId());

        if (CollectionUtil.isNotEmpty(orderRefunds)) {
            throw new GlobalException("该订单有退款信息正在处理当中，请处理完毕之后再进行发货的操作！");
        }

        Order orderParam = new Order();
        orderParam.setOrderId(order.getOrderId());
        if (!Objects.equals(order.getDvyType(), DvyType.FETCH.value()) || !Objects.equals(order.getDvyType(), DvyType.NOT_DELIVERY.value())){
            orderParam.setDvyId(deliveryOrderParam.getDvyId());
            orderParam.setDvyFlowId(deliveryOrderParam.getDvyFlowId());
        }
        orderParam.setDvyTime(new Date());
        orderParam.setUpdateTime(new Date());
        orderParam.setHbOrderStatus(OrderStatus.CONSIGNMENT.value());
        orderParam.setUserId(order.getUserId());

        orderService.delivery(orderParam);

        List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(deliveryOrderParam.getOrderNumber());
        for (OrderItem orderItem : orderItems) {
            productService.removeProductCacheByProdId(orderItem.getProdId());
            skuService.removeSkuCacheBySkuId(orderItem.getSkuId(),orderItem.getProdId());
        }
        return ResponseEntity.ok().build();
    }
    /**
     * 修改订单金额
     */
    @PutMapping("/changeAmount")
    public ResponseEntity<Void> changeAmount(@RequestBody Order order) {
        if(order.getFreightAmount()<0){
            throw new GlobalException("运费不能小于零");
        }
        if(Objects.isNull(order.getFreightAmount())){
            order.setFreightAmount(0.00);
        }
        orderService.changeAmount(order);
        return ResponseEntity.ok().build();
    }

    /**
     * 修改用户订单地址
     *
     * @param order
     * @return 是否修改成功
     */
    @SysLog("修改用户订单地址")
    @PutMapping("/changeUserAddr")
    public ResponseEntity<String> changeUserAddr(@RequestBody @Valid Order order) {
        Order orderDb = orderService.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getOrderId, order.getOrderId())
                .eq(Order::getOrderNumber,order.getOrderNumber())
        );
        if (orderDb.getHbOrderStatus() <= OrderStatus.PADYED.value() || Objects.equals(orderDb.getHbOrderStatus(),OrderStatus.WAIT_GROUP.value())){
            UserAddrOrder userAddrOrder = order.getUserAddrOrder();
            userAddrOrderService.updateById(userAddrOrder);
        }else {
            throw new GlobalException("订单状态异常，无法更改订单地址");
        }
        return ResponseEntity.ok().body("修改成功");
    }

    /**
     * 修改订单备注
     *
     * @param order
     * @return 是否修改成功
     */
    @SysLog("修改订单备注")
    @PutMapping("/changeOrderRamark")
    public ResponseEntity<String> changeOrderRamark(@RequestBody @Valid Order order) {
        Order orderDb = orderService.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getOrderId, order.getOrderId())
                .eq(Order::getOrderNumber,order.getOrderNumber())
        );
        orderDb.setShopRemarks(order.getShopRemarks());
        orderService.updateById(orderDb);
        return ResponseEntity.ok().body("修改成功");
    }

    /**
     * 已销售订单
     *
     * @param orderParam
     */
    @GetMapping("/soldExcel")
    public void soldExcel(OrderParam orderParam, HttpServletResponse response) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        orderParam.setShopId(shopId);
//        orderParam.setIsPayed(1);
        orderService.soldExcel(orderParam,response);
    }

    @PostMapping("/cancelOrder")
    @ApiOperation(value = "商家主动取消订单", notes = "商家主动取消订单")
//    public ResponseEntity<String> cancelOrder(@Valid @RequestBody com.yami.shop.bean.app.param.OrderRefundParam orderRefundParam) {
    public ResponseEntity<String> cancelOrder(@Valid @RequestBody CancelOrderParam cancelOrderParam) {

        // 获取订单信息
        Order order = orderService.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNumber, cancelOrderParam.getOrderNumber()));
        if (order == null) {
            throw new GlobalException("订单不存在");
        }
        if (!Objects.equals(order.getIsPayed(), 1)) {
            throw new GlobalException("当前订单还未付款，无法取消");
        }
        if (Objects.equals(order.getHbOrderStatus(), OrderStatus.CLOSE.value())) {
            throw new GlobalException("当前订单已失败");
        }

        // ========== 非市民请集合订单：原有逻辑 ==========
        com.yami.shop.bean.app.param.OrderRefundParam orderRefundParam = new com.yami.shop.bean.app.param.OrderRefundParam();
        orderRefundParam.setOrderNumber(cancelOrderParam.getOrderNumber());
        orderRefundParam.setRefundType(cancelOrderParam.getRefundType());
        orderRefundParam.setApplyType(cancelOrderParam.getApplyType());
        orderRefundParam.setIsReceiver(cancelOrderParam.getIsReceiver());
        orderRefundParam.setBuyerReason("商家主动取消订单");
        orderRefundParam.setBuyerDesc("商家后台取消订单");

        orderRefundParam.setBuyerMobile(order.getUserMobile());
        orderRefundParam.setRefundAmount(order.getTotal());

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


//        if (!Objects.equals(orderRefundParam.getRefundType(),RefundType.ALL.value()) && Objects.equals(order.getStatus(),OrderStatus.PADYED.value())) {
//            throw new GlobalException("未发货订单仅支持整单退款");
//        }
//        // 代发货整单退款不可以输入金额，为固定全额退款
//        if (Objects.equals(orderRefundParam.getRefundType(),RefundType.ALL.value()) && Objects.equals(order.getStatus(),OrderStatus.PADYED.value())) {
//            orderRefundParam.setRefundAmount(order.getActualTotal());
//        }

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

        //待收货 -> 整单退款 -> 退款金额 < 订单金额 - 运费金额
        if (Objects.equals(order.getHbOrderStatus(), OrderStatus.CONSIGNMENT.value()) && orderRefundParam.getRefundType().equals(RefundType.ALL.value())) {
            Double refundAmount = Arith.sub(order.getActualTotal(),order.getFreightAmount());
            if (orderRefundParam.getRefundAmount() > refundAmount){
                throw new GlobalException("退款金额已超出订单金额，无法申请");
            }
        }

        if (!orderRefundService.checkRefundDate(order)) {
            throw new GlobalException("当前订单已确认收货超过" + Constant.MAX_FINALLY_REFUND_TIME + "天，无法退款");
        }
        if (Objects.equals(order.getOrderType(),Constant.ORDER_TYPE_SCORE)) {
            throw new GlobalException("积分商品，无法退款");
        }
        if (Objects.equals(orderRefundParam.getRefundType(),RefundType.ALL.value()) && (!Objects.isNull(order.getRefundStatus()) && !Objects.equals(order.getRefundStatus(), RefundStatusEnum.DISAGREE.value()))) {
            throw new GlobalException("55该订单已有商品正在退款中，不能再进行整单退款");
        }
        // 生成退款单信息
        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("2002该订单正在进行整单退款，无法进行新的退款操作");
            }
            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());
        } else {
            // 部分物品退款
            OrderItem orderItem = orderItemService.getOne(new LambdaQueryWrapper<OrderItem>()
                    .eq(OrderItem::getOrderItemId, orderRefundParam.getOrderItemId())
                    .eq(OrderItem::getOrderNumber, orderRefundParam.getOrderNumber()));
            if (orderItem == null) {
                throw new GlobalException("该物品在订单中不存在");
            }
            boolean isCanRefund = false;
            //  查看是否有支付金额和积分都为空的订单，有则抛出异常
            for (OrderItem item : orderItemList) {
                if(item.getActualTotal() <= 0.0 && item.getUseScore() <= 0.0){
                    isCanRefund = true;
                    break;
                }
            }
            if (isCanRefund) {
                throw new GlobalException("该订单部分订单项支付金额和积分为0，无法使用部分退款！");
            }

            if (order.getPlatformAmount() > 0 && !Arith.isEquals(orderRefundParam.getRefundAmount(), orderItem.getActualTotal())) {
                throw new GlobalException("该订单有使用平台优惠，无法使用部分退款！");
            }
            // 计算该订单项的分销金额
            newOrderRefund.setDistributionTotalAmount(orderService.sumTotalDistributionAmountByOrderItem(Collections.singletonList(orderItem)));

            // 计算平台退款金额（退款时将这部分钱退回给平台，所以商家要扣除从平台这里获取的金额）
            //此处设置实际平台抵现金额
            newOrderRefund.setPlatformRefundAmount(orderItem.getPlatformShareReduce());

            // 退款物品数量为null或者0时，则为退款全部数量
            if (orderRefundParam.getGoodsNum() <= 0) {
                orderRefundParam.setGoodsNum(orderItem.getProdCount());
            }

            // 判断退款数量是否溢出
            if (orderRefundParam.getGoodsNum() > orderItem.getProdCount()) {
                throw new GlobalException("退款物品数量已超出订单中的数量，不允许申请");
            }

            // 判断退款金额是否超出订单金额
            double refundSingleAmount = Arith.div(orderRefundParam.getRefundAmount(), orderRefundParam.getGoodsNum(), 3);
            double singleAmount = Arith.div(orderItem.getActualTotal(), orderItem.getProdCount(), 3);
            if (refundSingleAmount > orderItem.getProductTotalAmount() || refundSingleAmount > singleAmount) {
                throw new GlobalException("退款金额已超出订单金额，无法申请");
            }

            // 一个订单项只能申请一次退款
            for (OrderRefund orderRefund : orderRefunds) {
                if (Objects.equals(orderRefund.getOrderId(), orderItem.getOrderItemId())) {
                    throw new GlobalException("退款订单项已处理，请勿重复申请");
                }
            }
        }

        newOrderRefund.setShopId(order.getShopId());
        newOrderRefund.setUserId(order.getUserId());
        newOrderRefund.setOrderId(order.getOrderId());
        newOrderRefund.setOrderNumber(order.getOrderNumber());
        newOrderRefund.setRefundSn(String.valueOf(snowflake.nextId()));
        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.setApplyTime(new Date());
        newOrderRefund.setUpdateTime(new Date());
        orderRefundService.applyRefund(newOrderRefund);
        return ResponseEntity.ok(newOrderRefund.getRefundSn());
    }

}
