

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

import cn.hutool.core.collection.CollectionUtil;
import com.tmerclub.cloud.api.delivery.dto.CalculateAndGetDeliverInfoDTO;
import com.tmerclub.cloud.api.delivery.feign.DeliveryFeignClient;
import com.tmerclub.cloud.api.order.manager.ConfirmOrderManager;
import com.tmerclub.cloud.api.order.manager.SubmitOrderManager;
import com.tmerclub.cloud.api.product.manager.ShopCartAdapter;
import com.tmerclub.cloud.api.product.manager.ShopCartItemAdapter;
import com.tmerclub.cloud.common.constant.StatusEnum;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.leaf.manager.SegmentManager;
import com.tmerclub.cloud.common.order.constant.DeliveryType;
import com.tmerclub.cloud.common.order.constant.OrderActivityType;
import com.tmerclub.cloud.common.order.constant.OrderType;
import com.tmerclub.cloud.common.order.util.OrderLangUtil;
import com.tmerclub.cloud.common.order.vo.*;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.security.AuthUserContext;
import com.tmerclub.cloud.seckill.constant.DistributedIdKey;
import com.tmerclub.cloud.seckill.dto.app.SeckillOrderDTO;
import com.tmerclub.cloud.seckill.dto.app.SubmitSeckillOrderDTO;
import com.tmerclub.cloud.seckill.manager.SeckillCacheManager;
import com.tmerclub.cloud.seckill.service.SeckillOrderService;
import com.tmerclub.cloud.seckill.service.SeckillService;
import com.tmerclub.cloud.seckill.service.SeckillSkuService;
import com.tmerclub.cloud.seckill.vo.SeckillSkuVO;
import com.tmerclub.cloud.seckill.vo.SeckillVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.apache.dubbo.config.annotation.DubboReference;
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 lhd
 * @date 2021-04-19 09:36:59
 */
@RestController
@RequestMapping("/seckillOrder")
@Tag(name = "秒杀订单接口")
public class SeckillOrderController {

    @Autowired
    private SeckillService seckillService;
    @Autowired
    private SeckillSkuService seckillSkuService;
    @Autowired
    private SeckillCacheManager seckillCacheManager;
    @Autowired
    private ConfirmOrderManager confirmOrderManager;
    @Autowired
    private ShopCartAdapter shopCartAdapter;
    @Autowired
    private ShopCartItemAdapter shopCartItemAdapter;
    @DubboReference
    private DeliveryFeignClient deliveryFeignClient;
    @Autowired
    private SubmitOrderManager submitOrderManager;
    @Autowired
    private SeckillOrderService seckillOrderService;
    @Autowired
    private SegmentManager segmentManager;


    @Operation(summary = "获取秒杀订单路径")
    @GetMapping("/getOrderPath")
    public ServerResponseEntity<String> getOrderPath(Long spuId) {
        Long userId = AuthUserContext.get().getUserId();
        SeckillVO seckill = seckillService.getBySpuId(spuId);
        // 前端看到这个状态码的时候，不用渲染活动页面了
        if (seckill == null || !Objects.equals(seckill.getStatus(), StatusEnum.ENABLE.value()) || seckill.getEndTime().getTime() < System.currentTimeMillis()) {
            return ServerResponseEntity.showFailMsg("活动已结束");
        }
        if (seckill.getStartTime().getTime() > System.currentTimeMillis()) {
            return ServerResponseEntity.showFailMsg("活动尚未开始");
        }
        String orderPath = seckillCacheManager.createOrderPath(userId + spuId);

        return ServerResponseEntity.success(orderPath);
    }


    @Operation(summary = "确认订单")
    @PostMapping("/{orderPath}/confirm")
    public ServerResponseEntity<ShopCartOrderMergerVO> confirm(@PathVariable("orderPath") String orderPath, @Valid @RequestBody SeckillOrderDTO orderParam) {

        Long userId = AuthUserContext.get().getUserId();

        Long spuId = orderParam.getShopCartItem().getSpuId();
        seckillCacheManager.checkOrderPath(userId + spuId, orderPath);

        SeckillSkuVO appSeckillSkuVO = seckillSkuService.getBySeckillSkuId(orderParam.getSeckillSkuId());
        if (appSeckillSkuVO == null || !Objects.equals(orderParam.getShopCartItem().getSkuId(), appSeckillSkuVO.getSkuId())) {
            throw new LuckException("sku 信息有误");
        }

        List<ShopCartItemVO> shopCartItemsDb = shopCartItemAdapter.conversionShopCartItem(orderParam.getShopCartItem(), appSeckillSkuVO.getSeckillPrice(), userId, orderParam.getDvyTypes());
        // 获取用户地址信息
        UserDeliveryInfoVO userDeliveryInfoVO = confirmOrderManager.getUserDeliveryInfoVO(shopCartItemsDb, userId, orderParam);
        // 将要返回给前端的完整的订单信息
        ShopCartOrderMergerVO shopCartOrderMerger = new ShopCartOrderMergerVO();
        shopCartOrderMerger.setDvyTypes(orderParam.getDvyTypes());
        shopCartOrderMerger.setOrderType(OrderType.SECKILL);
        shopCartOrderMerger.setSeckillSkuId(orderParam.getSeckillSkuId());
        shopCartOrderMerger.setActivityId(appSeckillSkuVO.getSeckillId());
        shopCartOrderMerger.setActivityType(OrderActivityType.SECKILL.value());

        // 筛选过滤掉不同配送的商品
        List<ShopCartItemVO> shopCartItems = confirmOrderManager.filterShopItemsByType(shopCartOrderMerger, userDeliveryInfoVO, shopCartItemsDb);
        OrderLangUtil.shopCartItemList(shopCartItems);
        // 无法配送的商品添加商品详细和店铺详细
        shopCartAdapter.setFilterShopItemsLong(shopCartOrderMerger);
        // 该商品不满足任何的配送方式
        if (CollectionUtil.isEmpty(shopCartItems)) {
            // 设置用户地址
            userDeliveryInfoVO = deliveryFeignClient.calculateAndGetDeliverInfo(new CalculateAndGetDeliverInfoDTO(shopCartItems, userDeliveryInfoVO)).getData();
            shopCartOrderMerger.setUserAddr(userDeliveryInfoVO.getUserAddr());
            return ServerResponseEntity.success(shopCartOrderMerger);
        }

        // 自提订单处理
        confirmOrderManager.handleStationOrder(shopCartOrderMerger, shopCartItems, userDeliveryInfoVO);


        // 商品类别 0.实物商品 1. 虚拟商品 2.组合商品
        int mold = 0;
        if (shopCartItemsDb.stream().filter(shopCartItemDto -> Objects.nonNull(shopCartItemDto.getMold()) && shopCartItemDto.getMold() == 1).count() == shopCartItemsDb.size()) {
            // 订单项中的所有商品都为虚拟商品时，才是虚拟订单
            mold = 1;
            shopCartOrderMerger.getDvyTypes().forEach(s -> s.setDvyType(DeliveryType.NOT_DELIVERY.value()));
        }
        shopCartOrderMerger.setSpuMold(mold);
        // 购物车
        List<ShopCartVO> shopCarts = shopCartAdapter.conversionShopCart(shopCartItems);
        // 计算运费，获取用户地址，自提信息
        ServerResponseEntity<UserDeliveryInfoVO> userDeliveryInfoResponseEntity = deliveryFeignClient.calculateAndGetDeliverInfo(new CalculateAndGetDeliverInfoDTO(shopCartItems, userDeliveryInfoVO));

        // 当算完一遍店铺的各种满减活动时，重算一遍订单金额
        confirmOrderManager.recalculateAmountWhenFinishingCalculateShop(shopCartOrderMerger, shopCarts, userDeliveryInfoResponseEntity.getData());

        // 处理完赠品后，插入订单项库存区域id
        confirmOrderManager.handleShopCartStockPoint(userDeliveryInfoVO, shopCarts, shopCartItemsDb, shopCartOrderMerger.getSpuMold());

        // 结束平台优惠的计算之后，还要重算一遍金额
        confirmOrderManager.recalculateAmountWhenFinishingCalculatePlatform(shopCartOrderMerger, userDeliveryInfoResponseEntity.getData());

        shopCartOrderMerger.getShopCartOrders().forEach(shopCartOrderVO -> shopCartOrderVO.setOrderType(OrderType.SECKILL.value()));

        // 计算平台佣金-跟订单其他金额是独立的，可以单独计算
        confirmOrderManager.confirmPlatformCommission(shopCartOrderMerger);

        // 缓存计算新
        confirmOrderManager.cacheCalculatedInfo(userId, shopCartOrderMerger);

        List<ShopCartOrderVO> shopCartOrders = shopCartOrderMerger.getShopCartOrders();
        // 移除没有商品项的店铺的订单信息
        shopCartOrders.removeIf(shopCartOrderVO -> shopCartOrderVO.getShopCartItemDiscounts().size() == 0);
        return ServerResponseEntity.success(shopCartOrderMerger);
    }

    /**
     * 购物车/立即购买  提交订单,根据店铺拆单
     */
    @PostMapping("/{orderPath}/submit")
    @Operation(summary = "提交订单", description = "提交之后返回WebSocket路径，请求对应的WebSocket路径，开始等待响应")
    public ServerResponseEntity<List<Long>> submitOrders(@PathVariable("orderPath") String orderPath, @Valid @RequestBody SubmitSeckillOrderDTO submitOrderParam) {
        Long userId = AuthUserContext.get().getUserId();


        // 在这里面已经生成了订单id了
        ServerResponseEntity<ShopCartOrderMergerVO> checkResult = submitOrderManager.checkSubmitInfo(submitOrderParam, userId);
        if (!checkResult.isSuccess()) {
            return ServerResponseEntity.transform(checkResult);
        }
        ShopCartOrderMergerVO mergerOrder = checkResult.getData();
        mergerOrder.setUserId(userId);
        ShopCartOrderVO shopCartOrderVO = mergerOrder.getShopCartOrders().get(0);
        ShopCartItemVO shopCartItemVO = shopCartOrderVO.getShopCartItemDiscounts().get(0).getShopCartItems().get(0);

        // 验证订单路径
        seckillCacheManager.checkOrderPath(userId + shopCartItemVO.getSpuId(), orderPath);

        // 秒杀活动信息（来自缓存）
        SeckillVO seckill = seckillService.getBySpuId(shopCartItemVO.getSpuId());

        // 前端看到这个状态码的时候，不用渲染活动页面了
        if (seckill == null || !Objects.equals(seckill.getStatus(), StatusEnum.ENABLE.value()) || seckill.getEndTime().getTime() < System.currentTimeMillis()) {
            return ServerResponseEntity.showFailMsg("活动已结束");
        }

        // 判断之前秒杀的商品有没有超过限制，-1表示商品不限制秒杀数量
        if (seckill.getMaxNum() != -1 && seckill.getMaxNum() < shopCartItemVO.getCount()) {
            return ServerResponseEntity.showFailMsg("超过购买限制");
        }
        // 判断之前秒杀的商品有没有超过限制，-1表示商品不限制秒杀数量
        boolean isOverNum = seckillOrderService.checkOrderSpuNum(seckill, mergerOrder.getUserId(), shopCartItemVO.getCount());
        if (!isOverNum) {
            return ServerResponseEntity.showFailMsg("超过购买限制");
        }

        // 生成订单id
        Long orderId = segmentManager.getSegmentIdWithDateTime(DistributedIdKey.tmerclub_ORDER, mergerOrder.getUserId());
        shopCartOrderVO.setOrderId(orderId);

        mergerOrder.setActivityId(seckill.getSeckillId());
        mergerOrder.setActivityType(OrderActivityType.SECKILL.value());
        mergerOrder.setCreateTime(new Date());
        seckillOrderService.submit(mergerOrder, seckill.getSeckillId(), seckill.getMaxNum());

        return ServerResponseEntity.success(Collections.singletonList(shopCartOrderVO.getOrderId()));
    }

}
