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

package com.yami.shop.groupbuy.comment.service.impl;


import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.enums.OrderStatus;
import com.yami.shop.bean.enums.OrderType;
import com.yami.shop.bean.model.*;
import com.yami.shop.common.exception.GlobalException;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.dao.OrderSettlementMapper;
import com.yami.shop.dao.ProductMapper;
import com.yami.shop.dao.SkuMapper;
import com.yami.shop.groupbuy.comment.api.dto.ApiGroupSkuInfoDto;
import com.yami.shop.groupbuy.comment.api.dto.ApiGroupUserDto;
import com.yami.shop.groupbuy.comment.api.dto.ApiGroupUserOrderDto;
import com.yami.shop.groupbuy.comment.dao.GroupOrderMapper;
import com.yami.shop.groupbuy.comment.dao.GroupTeamMapper;
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.GroupTeam;
import com.yami.shop.groupbuy.comment.service.GroupOrderService;
import com.yami.shop.groupbuy.comment.service.GroupSkuService;
import com.yami.shop.service.*;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author LGH
 * @date 2019-08-27 17:55:57
 */
@Service
@AllArgsConstructor
public class GroupOrderServiceImpl extends ServiceImpl<GroupOrderMapper, GroupOrder> implements GroupOrderService {

    private final GroupOrderMapper groupOrderMapper;
    private final Snowflake snowflake;
    private final MapperFacade mapperFacade;
    private final UserAddrOrderService userAddrOrderService;
    private final SkuService skuService;
    private final OrderSettlementMapper orderSettlementMapper;
    private final OrderService orderService;
    private final OrderItemService orderItemService;
    private final SkuMapper skuMapper;
    private final ProductService productService;
    private final ProductMapper productMapper;
    private final GroupTeamMapper groupTeamMapper;
    private final GroupSkuService groupSkuService;

    /**
     * 获取参团的用户列表
     *
     * @param groupTeamId 拼团单ID
     * @return ApiGroupUserDto列表
     */
    @Override
    public List<ApiGroupUserDto> listApiGroupUserDto(Long groupTeamId) {
        return groupOrderMapper.listApiGroupUserDto(groupTeamId);
    }
    //@CachePut 的作用 主要针对方法配置，能够根据方法的请求参数对其结果进行缓存，和 @Cacheable 不同的是，它每次都会触发真实方法的调用
    @Override
    @CachePut(cacheNames = "ApiGroupUserOrderDto", key = "#userId")
    public ApiGroupUserOrderDto putConfirmOrderCache(String userId, ApiGroupUserOrderDto apiGroupUserOrderDto) {
        return apiGroupUserOrderDto;
    }
    //@Cacheable 的作用 主要针对方法配置，能够根据方法的请求参数对其结果进行缓存
    @Override
    @Cacheable(cacheNames = "ApiGroupUserOrderDto", key = "#userId")
    public ApiGroupUserOrderDto getConfirmOrderCache(String userId) {
        return null;
    }

    @Override
    @CacheEvict(cacheNames = "ApiGroupUserOrderDto", key = "#userId")
    public void removeConfirmOrderCache(String userId) {
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String submit(String userId, ApiGroupUserOrderDto hadConfirmOrder, String remark) {
        String orderNumber = "FD" + snowflake.nextId();
        Date now = new Date();
        // 获取订单地址
        UserAddrOrder userAddrOrder = mapperFacade.map(hadConfirmOrder.getUserAddrDto(), UserAddrOrder.class);
        if (Objects.isNull(userAddrOrder)) {
            throw new GlobalException("请填写收货地址");
        }
        userAddrOrder.setUserId(userId);
        userAddrOrder.setCreateTime(now);
        userAddrOrderService.save(userAddrOrder);

        // 检验并更新商品
        Product product = productService.getProductByProdId(hadConfirmOrder.getProdId());
        if (Objects.isNull(product)) {
            throw new GlobalException("查找不到该商品信息");
        }
        if (product.getStatus() != 1) {
            throw new GlobalException("商品[" + product.getProdName() + "]已下架");
        }
        Product calProd = new Product();
        calProd.setProdId(product.getProdId());
        calProd.setTotalStocks(hadConfirmOrder.getProdTotalCount());
        if (productMapper.updateStocks(calProd) == 0) {
            throw new GlobalException("商品：[" + product.getProdName() + "]库存不足8");
        }

        // 检验并更新商品规格
        ApiGroupSkuInfoDto apiGroupSkuInfoDto = groupSkuService.getSkuInfoByGroupSkuId(hadConfirmOrder.getGroupSkuId());
        if (Objects.isNull(apiGroupSkuInfoDto)) {
            throw new GlobalException("商品已售空或已下架");
        }
        if (apiGroupSkuInfoDto.getStocks() != -1 && apiGroupSkuInfoDto.getStocks() < hadConfirmOrder.getProdTotalCount()) {
            throw new GlobalException("库存量不足，请重新选择购买数量");
        }
        Sku sku = new Sku();
        sku.setSkuId(apiGroupSkuInfoDto.getSkuId());
        sku.setStocks(hadConfirmOrder.getProdTotalCount());
        if (apiGroupSkuInfoDto.getStocks() != -1) {
            if (skuMapper.updateStocks(sku) <= 0) {
                throw new GlobalException("商品：[" + apiGroupSkuInfoDto.getProdName() + "]库存不足9");
            }
        }
        // 插入订单
        Order order = new Order();
        order.setUserId(userId);
        order.setAddrOrderId(userAddrOrder.getAddrOrderId());
        order.setOrderNumber(orderNumber);
        order.setCreateTime(now);
        order.setUpdateTime(now);
        order.setHbOrderStatus(OrderStatus.UNPAY.value());
        order.setOrderType(OrderType.GROUP.value());
        order.setRemarks(remark);
        order.setIsPayed(0);
        order.setDeleteStatus(0);

        order.setShopId(hadConfirmOrder.getShopId());
        order.setProductNums(hadConfirmOrder.getProdTotalCount());
        order.setProdName(hadConfirmOrder.getProdName());
        order.setFreightAmount(hadConfirmOrder.getTransfee());
        order.setTotal(hadConfirmOrder.getProdTotalPrice());
        order.setReduceAmount(hadConfirmOrder.getDiscountPrice());
        order.setActualTotal(hadConfirmOrder.getOrderTotalPrice());
        order.setPlatformAmount(0.0);
        orderService.save(order);

        // 插入订单项
        OrderItem orderItem = new OrderItem();
        orderItem.setUserId(userId);
        orderItem.setOrderNumber(orderNumber);
        orderItem.setRecTime(now);
        orderItem.setCommSts(0);
        orderItem.setShareReduce(hadConfirmOrder.getDiscountPrice());

        orderItem.setSkuName(apiGroupSkuInfoDto.getSkuName());
        orderItem.setSkuId(apiGroupSkuInfoDto.getSkuId());
        orderItem.setProdName(apiGroupSkuInfoDto.getProdName());
        orderItem.setPic(StrUtil.isBlank(apiGroupSkuInfoDto.getSkuPic()) ? product.getPic() : apiGroupSkuInfoDto.getSkuPic());

        orderItem.setActualTotal(hadConfirmOrder.getOrderTotalPrice());
        orderItem.setShopId(hadConfirmOrder.getShopId());
        orderItem.setProdId(hadConfirmOrder.getProdId());
        orderItem.setProdCount(hadConfirmOrder.getProdTotalCount());
        orderItem.setPrice(hadConfirmOrder.getPrice());
        orderItem.setProductTotalAmount(hadConfirmOrder.getProdTotalPrice());
        orderItemService.save(orderItem);

        // 插入订单结算表
        OrderSettlement orderSettlement = new OrderSettlement();
        orderSettlement.setUserId(userId);
        orderSettlement.setOrderNumber(orderNumber);
        orderSettlement.setPayAmount(order.getActualTotal());
        orderSettlement.setCreateTime(now);
        orderSettlement.setPayStatus(0);
        orderSettlement.setIsClearing(0);
        orderSettlement.setVersion(0);
        orderSettlementMapper.insert(orderSettlement);

        // 插入拼团订单
        GroupOrder groupOrder = new GroupOrder();
        groupOrder.setGroupTeamId(hadConfirmOrder.getGroupTempId());

        // 如果为团长，则需新建拼团团队
        if (hadConfirmOrder.getGroupTempId() == 0) {
            GroupTeam groupTeam = new GroupTeam();
            groupTeam.setShareUserId(userId);
            groupTeam.setGroupProdId(hadConfirmOrder.getGroupProdId());
            groupTeam.setGroupActivityId(hadConfirmOrder.getGroupActivityId());
            groupTeam.setJoinNum(1);
            groupTeam.setCreateTime(now);
            groupTeam.setUpdateTime(now);
            groupTeam.setShopId(hadConfirmOrder.getShopId());
            groupTeam.setStatus(TeamStatusEnum.WAITING_GROUP.value());
            groupTeamMapper.insert(groupTeam);
            groupOrder.setGroupTeamId(groupTeam.getGroupTeamId());
        }

        groupOrder.setUserId(userId);
        groupOrder.setOrderNumber(orderNumber);
        groupOrder.setActivityProdPrice(hadConfirmOrder.getActPrice());
        groupOrder.setPayPrice(hadConfirmOrder.getOrderTotalPrice());
        groupOrder.setShopId(hadConfirmOrder.getShopId());
        groupOrder.setIdentityType(Objects.equals(hadConfirmOrder.getGroupTempId(), 0L) ? 1 : 0);
        groupOrder.setStatus(GroupOrderStatusEnum.WAITING_PAY.value());
        groupOrder.setCreateTime(now);
        groupOrderMapper.insert(groupOrder);
        return orderNumber;
    }

    @Override
    public List<GroupOrder> listByGroupProdId(Long groupProdId, String userId) {
        return groupOrderMapper.listByGroupProdId(groupProdId, userId);
    }

    @Override
    public Integer getUserHadOrderCountByGroupProdId(String userId, Long groupProdId) {
        return groupOrderMapper.getUserHadOrderCountByGroupProdId(userId, groupProdId);
    }

    @Override
    public int getUserUnGroupOrderCount(String userId, Long groupProdId) {
        return groupOrderMapper.getUserUnGroupOrderCount(userId, groupProdId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int cancelGroupOrder(String orderNumber, int status) {
        return groupOrderMapper.cancelGroupOrder(orderNumber, status);
    }

}
