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

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

import cn.hutool.core.util.StrUtil;
import com.yami.shop.bean.app.dto.OrderNumbersDto;
import com.yami.shop.bean.app.dto.ProductItemDto;
import com.yami.shop.bean.app.dto.UserAddrDto;
import com.yami.shop.bean.enums.ProdStatusEnums;
import com.yami.shop.bean.event.CalculateTransfeeEvent;
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.groupbuy.comment.api.dto.ApiGroupActivityDto;
import com.yami.shop.groupbuy.comment.api.dto.ApiGroupSkuInfoDto;
import com.yami.shop.groupbuy.comment.api.dto.ApiGroupUserOrderDto;
import com.yami.shop.groupbuy.comment.api.param.ApiGroupOrderParam;
import com.yami.shop.groupbuy.comment.api.param.ApiGroupOrderSubmitParam;
import com.yami.shop.groupbuy.comment.enums.ActivityStatusEnum;
import com.yami.shop.groupbuy.comment.enums.GroupOrderStatusEnum;
import com.yami.shop.groupbuy.comment.enums.TeamStatusEnum;
import com.yami.shop.groupbuy.comment.model.GroupOrder;
import com.yami.shop.groupbuy.comment.model.GroupProd;
import com.yami.shop.groupbuy.comment.model.GroupTeam;
import com.yami.shop.groupbuy.comment.service.*;
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.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

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

@RestController
@RequestMapping("/p/group/order")
@Api(tags = "拼团订单接口")
@AllArgsConstructor
public class GroupOrderController {

    private final GroupTeamService groupTeamService;
    private final GroupOrderService groupOrderService;
    private final UserAddrService userAddrService;
    private final ApplicationContext applicationContext;
    private final MapperFacade mapperFacade;
    private final GroupProdService groupProdService;
    private final GroupSkuService groupSkuService;
    private final GroupActivityService groupActivityService;
    private final SkuService skuService;
    private final ProductService productService;


    @PostMapping("/confirm")
    @ApiOperation(value = "确认订单", notes = "传入参团/开团所需要的参数进行下单,如果用户为开团时拼团团队Id(groupTeamId)为0,如用户为开团则需要将拼团团队Id(groupTeamId)需要带上")
    public ResponseEntity<ApiGroupUserOrderDto> confirm(@Valid @RequestBody ApiGroupOrderParam apiGroupOrderParam) {
        String userId = SecurityUtils.getUser().getUserId();
        if (apiGroupOrderParam.getGroupTeamId() != 0) {
            GroupTeam groupTeam = groupTeamService.getById(apiGroupOrderParam.getGroupTeamId());
            if (Objects.isNull(groupTeam)) {
                throw new GlobalException("未找到拼团团队信息");
            }
            if (!TeamStatusEnum.IN_GROUP.value().equals(groupTeam.getStatus())) {
                throw new GlobalException("拼团团队不在拼团中，不能参与拼团");
            }
        }
        GroupProd groupProd = groupProdService.getGroupProdByGroupSkuId(apiGroupOrderParam.getGroupSkuId());
        if (Objects.isNull(groupProd) || !Objects.equals(groupProd.getStatus(), 1)) {
            throw new GlobalException("活动商品不在正常状态");
        }
        // 校验商品规格信息
        ApiGroupSkuInfoDto groupSkuInfoDto = groupSkuService.getSkuInfoByGroupSkuId(apiGroupOrderParam.getGroupSkuId());
        if (Objects.isNull(groupSkuInfoDto)) {
            throw new GlobalException("活动商品规格已售空或已下架");
        }
        if (groupSkuInfoDto.getProdStatus() != ProdStatusEnums.NORMAL.getValue()) {
            throw new GlobalException("活动商品不在上架状态，确认订单失败");
        }
        // 校验活动
        ApiGroupActivityDto groupActivityInfo = groupActivityService.getApiGroupActivityInfo(groupProd.getGroupActivityId(), groupProd.getProdId());
        if (!Objects.equals(groupActivityInfo.getActivityStatus(), ActivityStatusEnum.UNDER_WAY.value())) {
            throw new GlobalException("拼团活动不在进行中，请稍后重试");
        }
        if (groupSkuInfoDto.getStocks() != -1 && groupSkuInfoDto.getStocks() < apiGroupOrderParam.getProdCount()) {
            throw new GlobalException("库存量不足，请重新选择购买数量");
        }
        if (Objects.equals(groupActivityInfo.getHasMaxNum(), 1)) {
            Integer hasOrderCount = groupOrderService.getUserHadOrderCountByGroupProdId(userId, groupProd.getGroupProdId());
            if (hasOrderCount + apiGroupOrderParam.getProdCount() > groupActivityInfo.getMaxNum()) {
                String prodName = StrUtil.isEmpty(groupSkuInfoDto.getSkuName()) ? groupSkuInfoDto.getProdName() : groupSkuInfoDto.getSkuName();
                throw new GlobalException("活动商品【" + prodName + "】限购数量为" + groupActivityInfo.getMaxNum() + "件，您已购买" + hasOrderCount + "件，现购" + apiGroupOrderParam.getProdCount() + "件,超出最大的购买数量");
            }
        }
        // 查看未完成的订单数量
        int unGroupOrderCount = groupOrderService.getUserUnGroupOrderCount(userId, groupProd.getGroupProdId());
        if (unGroupOrderCount > 0) {
            throw new GlobalException("您已有待成团或拼团中的订单，请在拼团成功后重试");
        }

        // 计算商品总金额
        double prodTotalPrice = Arith.mul(apiGroupOrderParam.getProdCount(), groupSkuInfoDto.getActPrice());

        // 计算运费
        ProductItemDto productItemDto = new ProductItemDto();
        productItemDto.setProdId(groupProd.getProdId());
        productItemDto.setSkuId(groupSkuInfoDto.getSkuId());
        productItemDto.setProdCount(apiGroupOrderParam.getProdCount());
        productItemDto.setProductTotalAmount(prodTotalPrice);

        // 用户地址信息
        UserAddr userAddr = userAddrService.getUserAddrByUserId(apiGroupOrderParam.getAddrId(), userId);
        double transFee = 0.0;
        if (userAddr != null) {
//            transFee = transportManagerService.calculateTransfee(productItemDto, userAddr);
            CalculateTransfeeEvent calculateTransfeeEvent = new CalculateTransfeeEvent(productItemDto, userAddr);
            applicationContext.publishEvent(calculateTransfeeEvent);
            transFee = calculateTransfeeEvent.getTransfee();
        }

        // 需要支付的总金额
        double orderTotalPrice = 0.0;
        // 是否享受团长价（团id为0表示这个团还没开始，也就是这个人是团长，因为id是long类型，所以用equals）
        if (Objects.equals(apiGroupOrderParam.getGroupTeamId(), 0L) && groupActivityInfo.getHasLeaderPrice() == 1) {
            orderTotalPrice = Arith.add(Arith.mul(apiGroupOrderParam.getProdCount(), groupSkuInfoDto.getLeaderPrice()), transFee);
        } else {
            // 参团为活动价格
            orderTotalPrice = Arith.add(prodTotalPrice, transFee);
        }



        // 封装返回的信息
        ApiGroupUserOrderDto apiGroupUserOrderDto = mapperFacade.map(groupSkuInfoDto, ApiGroupUserOrderDto.class);
        apiGroupUserOrderDto.setUserAddrDto(mapperFacade.map(userAddr, UserAddrDto.class));

        apiGroupUserOrderDto.setOrderTotalPrice(orderTotalPrice);
        apiGroupUserOrderDto.setTransfee(transFee);
        apiGroupUserOrderDto.setProdTotalPrice(prodTotalPrice);

        Sku sku = skuService.getSkuBySkuId(groupSkuInfoDto.getSkuId());

        // 计算原来的商品总金额
        double oriTotalPrice = Arith.mul(apiGroupOrderParam.getProdCount(), sku.getPrice());
        // 原商品总价 - 商品总价格(团购总不能没有优惠金额吧)
        apiGroupUserOrderDto.setDiscountPrice(Math.max(Arith.sub(oriTotalPrice, prodTotalPrice), 0));

        apiGroupUserOrderDto.setGroupActivityId(groupActivityInfo.getGroupActivityId());
        apiGroupUserOrderDto.setProdId(groupProd.getProdId());
        apiGroupUserOrderDto.setGroupTempId(apiGroupOrderParam.getGroupTeamId());
        apiGroupUserOrderDto.setGroupSkuId(apiGroupOrderParam.getGroupSkuId());
        apiGroupUserOrderDto.setProdTotalCount(apiGroupOrderParam.getProdCount());
        apiGroupUserOrderDto.setHasLeaderPrice(groupActivityInfo.getHasLeaderPrice());
        // 将数据放入缓存中
        groupOrderService.putConfirmOrderCache(userId, apiGroupUserOrderDto);
        return ResponseEntity.ok(apiGroupUserOrderDto);
    }

    @PostMapping("/submit")
    @ApiOperation(value = "提交订单，返回订单编号", notes = "根据订单信息，返回订单编号")
    public ResponseEntity<OrderNumbersDto> submitOrders(@Valid @RequestBody ApiGroupOrderSubmitParam apiGroupOrderSubmitParam) {
        String userId = SecurityUtils.getUser().getUserId();
        ApiGroupUserOrderDto hadConfirmOrder = groupOrderService.getConfirmOrderCache(userId);
        if (Objects.isNull(hadConfirmOrder)) {
            throw new GlobalException("订单已过期，请重新下单");
        }
        if (Objects.isNull(hadConfirmOrder.getUserAddrDto())) {
            throw new GlobalException("请填写正确的收货地址");
        }

        // 校验活动
        ApiGroupActivityDto apiGroupActivityInfo = groupActivityService.getApiGroupActivityInfo(hadConfirmOrder.getGroupActivityId(), hadConfirmOrder.getProdId());
        if (!Objects.equals(apiGroupActivityInfo.getActivityStatus(), ActivityStatusEnum.UNDER_WAY.value())) {
            throw new GlobalException("拼团活动不在进行中，不能参与拼团");
        }
        // 校验活动商品是否处于失效状态
        GroupProd groupProd = groupProdService.getGroupProdByGroupSkuId(hadConfirmOrder.getGroupSkuId());
        if (Objects.isNull(groupProd) || groupProd.getStatus() != 1) {
            throw new GlobalException("活动商品已失效或不存在");
        }
        List<GroupOrder> groupOrderList = groupOrderService.listByGroupProdId(groupProd.getGroupProdId(), userId);
        long count = groupOrderList.stream().filter(groupOrder -> Objects.equals(groupOrder.getStatus(), GroupOrderStatusEnum.WAITING_PAY.value())).count();
        if (count > 0) {
            throw new GlobalException("您正在参加此活动，请在拼团成功后重试");
        }
        // 校验拼团团队是否可以参团
        if (Objects.nonNull(hadConfirmOrder.getGroupTempId()) && hadConfirmOrder.getGroupTempId() != 0) {
            GroupTeam groupTeam = groupTeamService.getById(hadConfirmOrder.getGroupTempId());
            if (!Objects.equals(TeamStatusEnum.IN_GROUP.value(), groupTeam.getStatus())) {
                throw new GlobalException("该拼团团队已关闭，不能继续参团");
            }
            long hadJoinCount = groupOrderList.stream().filter(item -> Objects.equals(item.getGroupTeamId(), groupTeam.getGroupTeamId())).count();
            if (hadJoinCount > 0) {
                throw new GlobalException("您已参加过此团，不能重复参团");
            }
        }
        String orderNumber = groupOrderService.submit(userId, hadConfirmOrder, apiGroupOrderSubmitParam.getRemarks());
        // 移除缓存
        productService.removeProductCacheByProdId(hadConfirmOrder.getProdId());
        skuService.removeSkuCacheBySkuId(hadConfirmOrder.getSkuId(), hadConfirmOrder.getProdId());
        groupOrderService.removeConfirmOrderCache(userId);
        return ResponseEntity.ok(new OrderNumbersDto(orderNumber,false));
    }

}
