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

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


import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.app.dto.ProductItemDto;
import com.yami.shop.bean.enums.OrderStatus;
import com.yami.shop.bean.enums.OrderType;
import com.yami.shop.bean.enums.ScoreLogType;
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.OrderMapper;
import com.yami.shop.dao.OrderSettlementMapper;
import com.yami.shop.dao.ProductMapper;
import com.yami.shop.dao.SkuMapper;
import com.yami.shop.service.*;
import com.yami.shop.user.comment.dto.ScoreOrderMergerDto;
import com.yami.shop.user.comment.model.UserScoreDetail;
import com.yami.shop.user.comment.model.UserScoreLog;
import com.yami.shop.user.comment.service.ScoreOrderService;
import com.yami.shop.user.comment.service.UserScoreDetailService;
import com.yami.shop.user.comment.service.UserScoreLogService;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.collections.CollectionUtils;
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.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author LHD
 * @date 2019-12-12 13:55:57
 */
@Service
@AllArgsConstructor
public class ScoreOrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements ScoreOrderService {

    private final OrderItemService orderItemService;
    private final UserScoreDetailService userScoreDetailService;
    private final UserScoreLogService userScoreLogService;
    private final UserExtensionService userExtensionService;
    private final OrderMapper orderMapper;
    private final SkuMapper skuMapper;
    private final MapperFacade mapperFacade;
    private final SkuService skuService;
    private final ProductService productService;
    private final ProductMapper productMapper;
    private final UserAddrOrderService userAddrOrderService;
    private final Snowflake snowflake;
    private final OrderSettlementMapper orderSettlementMapper;

    @Override
    @CachePut(cacheNames = "ConfirmScoreOrderCache", key = "#userId")
    public ScoreOrderMergerDto putConfirmScoreOrderCache(String userId, ScoreOrderMergerDto scoreOrderMergerDto) {
        return scoreOrderMergerDto;
    }

    @Override
    @Cacheable(cacheNames = "ConfirmScoreOrderCache", key = "#userId")
    public ScoreOrderMergerDto getConfirmScoreOrderCache(String userId) {
        return null;
    }

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


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Order submit(String userId, ScoreOrderMergerDto mergerOrder) {
        // 提交订单
        Order scoreOrder = handlerOrder(mergerOrder);
        // 插入订单
        orderMapper.insert(scoreOrder);
        // 减少用户积分
        updateUserScore(mergerOrder,scoreOrder);
        // 插入订单项，返回主键
        orderItemService.saveBatch(scoreOrder.getOrderItems());

        return scoreOrder;
    }

    private void updateUserScore(ScoreOrderMergerDto mergerOrder,Order order) {
        UserExtension userExtension = userExtensionService.getOne(new LambdaQueryWrapper<UserExtension>().eq(UserExtension::getUserId, order.getUserId()));
        //查询积分详细表数据
        List<UserScoreDetail> scoreDetailList = userScoreDetailService.list(new LambdaQueryWrapper<UserScoreDetail>()
                .eq(UserScoreDetail::getUserId, userExtension.getUserId()).eq(UserScoreDetail::getStatus,1).orderByAsc(UserScoreDetail::getCreateTime));
        if(CollectionUtils.isEmpty(scoreDetailList)){
            throw new GlobalException("积分不足无法提交订单!");
        }
        int score = scoreDetailList.stream().mapToInt(UserScoreDetail::getUsableScore).sum();
        Integer scorePrice = mergerOrder.getProductItemDto().getScorePrice();
        List<UserScoreDetail> updateScoreDetails = new ArrayList<>();
        if(userExtension.getScore() < scorePrice || score < scorePrice){
            throw new GlobalException("积分不足无法提交订单!");
        }
        UserScoreLog userScoreLog = new UserScoreLog();
        userScoreLog.setUserId(order.getUserId());
        userScoreLog.setBizId(order.getOrderId());
        userScoreLog.setScore(scorePrice);
        userScoreLog.setSource(ScoreLogType.SCORE_CASH.value());
        userScoreLog.setCreateTime(new Date());
        userScoreLog.setIoType(0);
        // 修改积分明细，如果当前明细不够扣除在进行下一条
        // 如果够添加一条积分明细记录
        for (UserScoreDetail scoreDetail : scoreDetailList) {
            if(scoreDetail.getUsableScore() <= scorePrice){
                scoreDetail.setStatus(0);
                scoreDetail.setBizId(order.getOrderId());
                updateScoreDetails.add(scoreDetail);

                scorePrice -= scoreDetail.getUsableScore();
            }else{
                UserScoreDetail addDetail = new UserScoreDetail();
                addDetail.setCreateTime(scoreDetail.getCreateTime());
                addDetail.setStatus(0);
                addDetail.setUserId(scoreDetail.getUserId());
                addDetail.setBizId(order.getOrderId());
                addDetail.setUsableScore(scorePrice);
                userScoreDetailService.save(addDetail);

                scoreDetail.setUsableScore(scoreDetail.getUsableScore() - scorePrice);
                updateScoreDetails.add(scoreDetail);
                break;
            }
            if(scorePrice <= 0){
                break;
            }
        }
        userScoreLogService.save(userScoreLog);
        userScoreDetailService.updateBatchById(updateScoreDetails);
        //保存用户积分
        userExtension.setScore(userExtension.getScore() - mergerOrder.getProductItemDto().getScorePrice());
        userExtensionService.updateById(userExtension);
    }

    private Order handlerOrder(ScoreOrderMergerDto mergerOrder){
        Date now = new Date();
        String userId = mergerOrder.getUserId();
        // 订单商品参数
        ProductItemDto productItemDto = mergerOrder.getProductItemDto();
        // 把订单地址保存到数据库
        UserAddrOrder userAddrOrder = mapperFacade.map(mergerOrder.getUserAddr(), UserAddrOrder.class);
        if (userAddrOrder == null) {
            throw new GlobalException("请填写收货地址");
        }
        userAddrOrder.setUserId(userId);
        userAddrOrder.setCreateTime(now);
        userAddrOrderService.save(userAddrOrder);
        if(Objects.isNull(productItemDto)) {
            throw new GlobalException("订单已经失效");
        }
        // 订单地址id
        Long addrOrderId = userAddrOrder.getAddrOrderId();
        //检查sku和prod的库存
        Sku sku = checkAndGetSku(productItemDto.getSkuId(), productItemDto);
        Product product = checkAndGetProd(productItemDto.getProdId(), productItemDto);

        // 使用雪花算法生成的订单号
        String orderNumber = "FD" + snowflake.nextId( );
        mergerOrder.setOrderNumber(orderNumber);

        Long shopId = mergerOrder.getShopId();
        List<OrderItem> orderItems = new ArrayList<>();
        OrderItem orderItem = mapperFacade.map(productItemDto, OrderItem.class);
        orderItem.setPic(StrUtil.isBlank(sku.getPic()) ? product.getPic() : sku.getPic());
        orderItem.setShopId(shopId);
        orderItem.setOrderNumber(orderNumber);
        orderItem.setUserId(userId);
        orderItem.setRecTime(now);
        orderItem.setUseScore(mergerOrder.getProductItemDto().getScorePrice());
        orderItem.setCommSts(0);
        orderItems.add(orderItem);
        // 订单信息
        Order order = new Order();
        order.setShopId(shopId);
        order.setOrderNumber(orderNumber);
        // 订单商品名称
        order.setProdName(orderItem.getProdName());
        // 用户id
        order.setUserId(userId);
        // 商品总额
        order.setTotal(mergerOrder.getTotal());
        // 实际总额
        order.setActualTotal(mergerOrder.getActualTotal());
        order.setPlatformAmount(0.0);
        order.setHbOrderStatus(OrderStatus.UNPAY.value());
        order.setUpdateTime(now);
        order.setCreateTime(now);
        order.setIsPayed(0);
        order.setDeleteStatus(0);
        order.setProductNums(mergerOrder.getTotalCount());
        order.setAddrOrderId(addrOrderId);
        order.setOrderType(OrderType.SCORE.value());
        order.setReduceAmount(0.00);
        order.setFreightAmount(0.00);
        order.setRemarks(mergerOrder.getRemarks());

        order.setOrderItems(orderItems);
         //插入订单结算表
        OrderSettlement orderSettlement = new OrderSettlement();
        orderSettlement.setUserId(userId);
        orderSettlement.setIsClearing(0);
        orderSettlement.setCreateTime(now);
        orderSettlement.setOrderNumber(orderNumber);
        orderSettlement.setPayAmount(order.getActualTotal());
        orderSettlement.setPayStatus(0);
        orderSettlement.setVersion(0);
        //如果用使用积分，结算表将积分价格插入
        if(mergerOrder.getIsScorePay() != null && mergerOrder.getIsScorePay() == 1 && mergerOrder.getProductItemDto() != null){
            orderSettlement.setPayScore(mergerOrder.getProductItemDto().getScorePrice());
        }
        orderSettlementMapper.insert(orderSettlement);
        Sku updateSku = new Sku();
        updateSku.setSkuId(sku.getSkuId());
        updateSku.setStocks(orderItem.getProdCount());
        Product updateProd = new Product();
        updateProd.setProdId(sku.getProdId());
        updateProd.setTotalStocks(orderItem.getProdCount());
        // 更新sku库存
        if (skuMapper.updateStocks(updateSku) == 0) {
            skuService.removeSkuCacheBySkuId(sku.getSkuId(), sku.getProdId());
            productService.removeProductCacheByProdId(sku.getProdId());
            throw new GlobalException("商品：[" + sku.getProdName() + "]库存不足1");
        }
        // 更新商品库存
        if (productMapper.updateStocks(updateProd) == 0) {
            productService.removeProductCacheByProdId(product.getProdId());
            throw new GlobalException("商品：[" + product.getProdName() + "]库存不足2");
        }
//        // 更新sku库存
//        if (skuMapper.updateStocks(sku) == 0) {
//            skuService.removeSkuCacheBySkuId(sku.getSkuId(), sku.getProdId());
//            productService.removeProductCacheByProdId(sku.getProdId());
//            throw new GlobalException("商品：[" + sku.getProdName() + "]库存不足");
//        }
//        // 更新商品库存
//        if (productMapper.updateStocks(product) == 0) {
//            productService.removeProductCacheByProdId(product.getProdId());
//            throw new GlobalException("商品：[" + product.getProdName() + "]库存不足");
//        }
        return order;
    }



    @SuppressWarnings({"Duplicates"})
    private Sku checkAndGetSku(Long skuId, ProductItemDto shopCartItem) {
        // 获取sku信息
        Sku sku = skuService.getSkuBySkuId(skuId);
        if (sku == null) {
            throw new GlobalException("购物车包含无法识别的商品");
        }

        if (sku.getStatus() != 1) {
            throw new GlobalException("商品[" + sku.getProdName() + "]已下架");
        }
        // -1为无限库存
        if (sku.getStocks() != -1 && shopCartItem.getProdCount() > sku.getStocks()) {
            throw new GlobalException("商品：[" + sku.getProdName() + "]库存不足3");
        }

        if (sku.getStocks() != -1) {
            // 这里的库存是改变的库存
            sku.setStocks(shopCartItem.getProdCount());
        }
        return sku;
    }

    @SuppressWarnings({"Duplicates"})
    private Product checkAndGetProd(Long prodId, ProductItemDto productItemDto) {
        Product product = productService.getProductByProdId(prodId);
        if (product == null) {
            throw new GlobalException("购物车包含无法识别的商品");
        }
        if (product.getStatus() != 1) {
            throw new GlobalException("商品[" + product.getProdName() + "]已下架");
        }
        Integer totalStocks = product.getTotalStocks();
        // 商品需要改变的库存
        if (totalStocks != -1) {
            product.setTotalStocks(productItemDto.getProdCount());
        }
        // -1为无限库存
        if (totalStocks != -1 && product.getTotalStocks() > totalStocks) {
            throw new GlobalException("商品：[" + product.getProdName() + "]库存不足4");
        }
        return product;
    }

}
