package com.qs.mp.channel.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.qs.mp.admin.domain.Coupon;
import com.qs.mp.admin.service.ICouponService;
import com.qs.mp.channel.domain.ChannelCouponVerifyLog;
import com.qs.mp.channel.domain.ChannelGoods;
import com.qs.mp.channel.domain.ChannelMoneyLog;
import com.qs.mp.channel.mapper.ChannelCouponVerifyLogMapper;
import com.qs.mp.channel.service.IChannelCouponVerifyLogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qs.mp.channel.service.IChannelGoodsService;
import com.qs.mp.channel.service.IChannelMoneyLogService;
import com.qs.mp.common.enums.*;
import com.qs.mp.common.exception.ServiceException;
import com.qs.mp.common.utils.LogUtil;
import com.qs.mp.user.domain.UserCoupon;
import com.qs.mp.user.service.IUserCouponService;
import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

/**
 * <p>
 * 渠道优惠券核销流水 服务实现类
 * </p>
 *
 * @author quanshu
 * @since 2022-03-21
 */
@Service
public class ChannelCouponVerifyLogServiceImpl extends ServiceImpl<ChannelCouponVerifyLogMapper, ChannelCouponVerifyLog> implements IChannelCouponVerifyLogService {

  protected final Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());

  @Autowired
  private ICouponService couponService;

  @Autowired
  private IUserCouponService userCouponService;

  @Autowired
  private IChannelMoneyLogService channelMoneyLogService;

  @Autowired
  private IChannelGoodsService channelGoodsService;

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void verify(Long channelId, UserCoupon userCoupon) {
    Date verifyDate = new Date();
    // 核销券
    boolean updateRst = userCouponService.update(new LambdaUpdateWrapper<UserCoupon>()
        .set(UserCoupon::getStatus, UserCouponStatusEnum.USED)
            .set(UserCoupon::getVerifyTime, verifyDate)
        .eq(UserCoupon::getId, userCoupon.getId())
        .eq(UserCoupon::getStatus, UserCouponStatusEnum.UNUSED));
    Assert.isTrue(updateRst, "经销商核销券时，券状态更新失败。userCouponId:" + userCoupon.getId());
    Coupon coupon = couponService.getById(userCoupon.getCouponId());

    // 记录核销日志
    ChannelCouponVerifyLog verifyLog = new ChannelCouponVerifyLog();
    verifyLog.setChannelId(channelId);
    verifyLog.setUserCouponId(userCoupon.getId());
    verifyLog.setVerifyCode(userCoupon.getVerifyCode());
    verifyLog.setTitle(coupon.getTitle());
    verifyLog.setDiscountType(coupon.getDiscountType());
    verifyLog.setDiscount(coupon.getDiscount());
    verifyLog.setDistributeTime(userCoupon.getCreatedTime());
    verifyLog.setValidStart(userCoupon.getValidStart());
    verifyLog.setValidEnd(userCoupon.getValidEnd());
    verifyLog.setVerifyTime(verifyDate);
    verifyLog.setSettleStatus(CouponSettleStatusEnum.FINISHED);
    save(verifyLog);

    if (coupon.getDiscountType() == CouponDiscountTypeEnum.MONEY_OFF){
      int logMoney = coupon.getDiscount() * (100 - coupon.getChannelSharedRate()) / 100;
      if (logMoney == 0) {
        LogUtil.warn(logger, "优惠券核销结算金额为0，忽略。userCouponId:{0}", userCoupon.getId());
      } else {
        // 结算
        ChannelMoneyLog moneyLog = new ChannelMoneyLog();
        moneyLog.setChannelId(channelId);
        moneyLog.setType(ChannelMoneyEnum.COUPON);
        moneyLog.setLogMoney(logMoney);
        moneyLog.setLogText("券码:" + userCoupon.getVerifyCode());
        moneyLog.setBizTime(new Date());
        moneyLog.setRefId(String.valueOf(verifyLog.getId()));
        channelMoneyLogService.changeMoney(moneyLog);
      }
    } else if (CouponDiscountTypeEnum.EXCHANGE == coupon.getDiscountType()) {
      LambdaQueryWrapper<ChannelGoods> queryWrapper = new LambdaQueryWrapper<ChannelGoods>()
              .eq(ChannelGoods::getChannelId, channelId)
              .eq(ChannelGoods::getRefId, coupon.getCouponId())
              .eq(ChannelGoods::getStatus, ChannelGoodsSettleStatusTypeEnum.NO)
              .ge(ChannelGoods::getRemainQty, 0)
              .orderByAsc(ChannelGoods::getCreatedTime);
      List<ChannelGoods> channelGoodsList = channelGoodsService.list(queryWrapper);
      if (CollectionUtils.isEmpty(channelGoodsList)) {
          LogUtil.error(logger, "门店下未进货绑定该优惠劵的商品，channelId:{0}, couponId:{1}", channelId, coupon.getCouponId());
        throw new ServiceException("商品未进货或库存不足，请前往采购商品");
      }
      ChannelGoods channelGoods = channelGoodsList.get(0);
      if (channelGoods.getRemainQty() == 0) {
        LogUtil.error(logger, "商品库存不足，无法核销，channelId:{0}, channel_goods_id:{1}", channelId, channelGoods.getId());
        throw new ServiceException("门店商品库存不足，无法核销,请前往采购商品");
      }
      boolean rst = channelGoodsService.update(new LambdaUpdateWrapper<ChannelGoods>()
              .set(ChannelGoods::getRemainQty, channelGoods.getRemainQty() - 1)
              .set(ChannelGoods::getVerifyQty, channelGoods.getVerifyQty() + 1)
              .set(channelGoods.getQuantity() == channelGoods.getVerifyQty() + 1,ChannelGoods::getStatus, ChannelGoodsSettleStatusTypeEnum.Verify)
              .eq(ChannelGoods::getId, channelGoods.getId()));
      Assert.isTrue(rst,"更新门店下铺设商品失败,channel_goods_id:" + channelGoods.getId());
    } else {
      LogUtil.warn(logger, "优惠券核销结算，类型非代金券，忽略。userCouponId:{0}", userCoupon.getId());
    }
  }

  @Override
  public Integer sumDisCountByQueryWrapper(QueryWrapper<ChannelCouponVerifyLog> queryWrapper) {
    return getBaseMapper().sumDisCountByQueryWrapper(queryWrapper);
  }
}
