/*
 * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 */

package com.yami.shop.seckill.api.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.StrUtil;
import com.yami.shop.bean.app.dto.UserAddrDto;
import com.yami.shop.bean.app.param.OrderShopParam;
import com.yami.shop.bean.event.CalculateTransfeeEvent;
import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.model.Sku;
import com.yami.shop.bean.model.UserAddr;
import com.yami.shop.common.exception.GlobalException;
import com.yami.shop.common.util.Arith;
import com.yami.shop.seckill.api.mq.redis.RedissonMsgHandler;
import com.yami.shop.seckill.api.param.ConfirmParam;
import com.yami.shop.seckill.api.service.SeckillCacheManager;
import com.yami.shop.seckill.comment.dto.SeckillOrderMergerDto;
import com.yami.shop.seckill.comment.dto.SeckillShopCartItemDto;
import com.yami.shop.seckill.comment.model.Seckill;
import com.yami.shop.seckill.comment.model.SeckillSku;
import com.yami.shop.seckill.comment.service.SeckillOrderService;
import com.yami.shop.seckill.comment.service.SeckillService;
import com.yami.shop.seckill.comment.service.SeckillSkuService;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.ProductService;
import com.yami.shop.service.SkuService;
import com.yami.shop.service.UserAddrService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import org.springframework.context.ApplicationContext;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.Date;
import java.util.Objects;


/**
 * 秒杀信息
 *
 * @author LGH
 * @date 2019-08-28 09:36:59
 */
@RestController
@AllArgsConstructor
@RequestMapping("/p/seckill" )
@Api(tags = "秒杀订单接口")
public class SeckillOrderController {

    private final SeckillService seckillService;

    private final MapperFacade mapperFacade;

    private final ProductService productService;

    private final SeckillSkuService seckillSkuService;

    private final SkuService skuService;

    private final UserAddrService userAddrService;


    private final SeckillOrderService seckillOrderService;

    private final ApplicationContext applicationContext;

    private final SeckillCacheManager seckillCacheManager;

    private final Snowflake snowflake;

    private final RedissonMsgHandler redissonMsgHandler;



    @ApiOperation(value = "获取秒杀订单路径")
    @GetMapping(value="/orderPath")
    public ResponseEntity<String> getOrderPath() {

        String userId = SecurityUtils.getUser().getUserId();

        String orderPath = seckillCacheManager.createOrderPath(userId);

        return ResponseEntity.ok(orderPath);
    }


    @ApiOperation(value = "确认订单")
    @PostMapping(value="/{orderPath}/confirm")
    public ResponseEntity<SeckillOrderMergerDto> confirm(@PathVariable("orderPath") String orderPath, @Valid @RequestBody ConfirmParam confirmParam) {

        String userId = SecurityUtils.getUser().getUserId();
        seckillCacheManager.checkOrderPath(userId,orderPath);

        // 秒杀sku（来自缓存），注：千万不要用这里的库存校验
        SeckillSku seckillSku = seckillSkuService.getSeckillSkuById(confirmParam.getSeckillSkuId());


        if (seckillSku == null) {
            throw new GlobalException("购物车包含无法识别的商品");
        }

        // 订单的地址信息
        UserAddr userAddr = userAddrService.getUserAddrByUserId(confirmParam.getAddrId(), userId);
        UserAddrDto userAddrDto = mapperFacade.map(userAddr, UserAddrDto.class);

        // 获取sku信息
        Sku sku = skuService.getSkuBySkuId(seckillSku.getSkuId());
        // 商品信息（来自缓存），注：千万不要用这里的库存校验
        Product product = productService.getProductByProdId(sku.getProdId());



        SeckillShopCartItemDto shopCartItem = new SeckillShopCartItemDto();
        shopCartItem.setProdName(sku.getProdName());
        shopCartItem.setProdId(product.getProdId());
        shopCartItem.setProdCount(confirmParam.getProdCount());
        // 商品总价格为：秒杀商品数量 * 秒杀价格
        shopCartItem.setProductTotalAmount(Arith.mul(confirmParam.getProdCount(), seckillSku.getSeckillPrice()));
        shopCartItem.setSkuId(sku.getSkuId());
        shopCartItem.setBasketDate(new Date());
        shopCartItem.setShareReduce(0.0);
        shopCartItem.setActualTotal(shopCartItem.getProductTotalAmount());
        shopCartItem.setShopId(product.getShopId());
        shopCartItem.setSkuName(sku.getSkuName());
        shopCartItem.setPic(StrUtil.isBlank(sku.getPic())? product.getPic() : sku.getPic());
        shopCartItem.setSeckillSkuId(seckillSku.getSeckillSkuId());
        shopCartItem.setSeckillId(seckillSku.getSeckillId());
        shopCartItem.setPrice(sku.getPrice());
        shopCartItem.setSeckillPrice(seckillSku.getSeckillPrice());
        //设置分销员卡号
        shopCartItem.setDistributionCardNo(confirmParam.getDistributionCardNo());
        // 用户地址如果为空，则表示该用户从未设置过任何地址相关信息
        double transFee = 0.0;
        if (userAddr != null) {
            // 每个产品的运费相加(运费模板有缓存)
            CalculateTransfeeEvent calculateTransfeeEvent = new CalculateTransfeeEvent(shopCartItem, userAddr);
            applicationContext.publishEvent(calculateTransfeeEvent);
            transFee = calculateTransfeeEvent.getTransfee();
        }

        shopCartItem.setActualTotal(shopCartItem.getProductTotalAmount());


        SeckillOrderMergerDto dto = new SeckillOrderMergerDto();
        dto.setActualTotal(Arith.add(shopCartItem.getProductTotalAmount(), transFee));
        dto.setShopCartItem(shopCartItem);
        dto.setTotal(shopCartItem.getProductTotalAmount());
        dto.setTotalCount(shopCartItem.getProdCount());
        dto.setUserAddr(userAddrDto);
        dto.setTransfee(transFee);

        seckillOrderService.putConfirmOrderCache(userId,dto);

        return ResponseEntity.ok(dto);
    }

    /**
     * 购物车/立即购买  提交订单,根据店铺拆单
     */
    @PostMapping("/{orderPath}/submit")
    @ApiOperation(value = "提交订单", notes = "提交之后返回WebSocket路径，请求对应的WebSocket路径，开始等待响应")
    public ResponseEntity<Void> submitOrders(@PathVariable("orderPath") String orderPath, @Valid @RequestBody OrderShopParam orderShopParam) {
        String userId = SecurityUtils.getUser().getUserId();

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

        SeckillOrderMergerDto dto = seckillOrderService.getConfirmOrderCache(userId);

        if (dto == null) {
            throw new GlobalException("订单已过期，请重新下单");
        }

        if (dto.getUserAddr() == null) {
            throw new GlobalException("请填写收货地址");
        }

        SeckillShopCartItemDto shopCartItem = dto.getShopCartItem();


        // 秒杀活动信息（来自缓存）
        Seckill seckill = seckillService.getSeckillById(shopCartItem.getSeckillId());

        // 秒杀已经下线
        if (Objects.equals(seckill.getStatus(), 0) || DateUtil.compare(seckill.getStartTime(),new Date()) > 0) {
            throw new GlobalException("秒杀活动已下线");
        }

        // 这里一进来就减库存，但是为了防止少卖，120秒会自己更新库存~因为缓存只有60秒
        seckillCacheManager.decrSeckillSkuStocks(shopCartItem.getSeckillSkuId(),shopCartItem.getSeckillId(), shopCartItem.getProdCount());



        // 判断之前秒杀的商品有没有超过限制，-1表示商品不限制秒杀数量
        seckillOrderService.checkOrderProdNum(seckill, userId, shopCartItem.getProdCount());


        dto.setMsgId(orderPath);
        dto.setRemarks(orderShopParam.getRemarks());
        dto.setUserId(userId);
        redissonMsgHandler.sendChannelMess("seckill",dto);
        seckillOrderService.removeConfirmOrderCache(userId);

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




}
