package com.cyksj.service.mange.coupon.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.util.Jsons;
import com.cyksj.mapper.GoodsDonMapper;
import com.cyksj.mapper.GoodsDonSkuMapper;
import com.cyksj.mapper.GroupsRelationExpiryRecordMapper;
import com.cyksj.mapper.UserMapper;
import com.cyksj.mapper.manage.coupon.*;
import com.cyksj.model.entity.*;
import com.cyksj.model.request.CouponActiveReq;
import com.cyksj.model.request.CouponDistributeReq;
import com.cyksj.service.coupon.CouponFontService;
import com.cyksj.service.mange.coupon.CouponCommonService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

/*
 *项目名: netflix
 *文件名: CouponCommonServiceImpl
 *创建者: JavaZou
 *创建时间:2022/11/17 17:00
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class CouponCommonServiceImpl implements CouponCommonService {
	private final GoodsDonSkuMapper goodsDonSkuMapper;

	private final CouponMapper couponMapper;

	private final CouponActiveMapper couponActiveMapper;

	private final CouponRecommendMapper couponRecommendMapper;

	private final CouponDistributePopularizeMapper couponDistributePopularizeMapper;

	private final CouponSkuMapper couponSkuMapper;

	private final UserMapper userMapper;

	private final CouponUserMapper couponUserMapper;

	private final GoodsDonMapper goodsDonMapper;

	private final CouponFontService couponFontService;

	private final GroupsRelationExpiryRecordMapper groupsRelationExpiryRecordMapper;
	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void saveCoupon(Coupon coupon) throws Exception {
		checkCouponParamsAndSaveOrUpdate(coupon);
	}

	@Override
	public void updateCoupon(Coupon coupon) throws Exception {
		if (coupon.getId() == null || coupon.getId() < 1) {
			throw BusinessRuntimeException.getInstance("请输入正确的优惠券id");
		}
		if (coupon.getType() == Coupon.Type.reduce) {
			coupon.setDiscount(BigDecimal.ZERO);
		}
		if (coupon.getType() == Coupon.Type.discount) {
			coupon.setReduceCondition(BigDecimal.ZERO);
			coupon.setReduceMoney(BigDecimal.ZERO);
		}
		Coupon entity = couponMapper.selectById(coupon.getId());
		if (entity == null || !entity.getDeleted()) {
			throw BusinessRuntimeException.getInstance("该优惠券不存在");
		}
		checkCouponParamsAndSaveOrUpdate(coupon);
	}

	@Override
	public void sendCoupon(CouponActiveReq couponActiveReq) {
		Coupon coupon = couponMapper.selectById(couponActiveReq.getCouponId());
		if (coupon == null || !coupon.getDeleted()) {
			throw BusinessRuntimeException.getInstance("该优惠券不存在");
		}
		if (!coupon.getSendStatus()) {
			coupon.setSendStatus(!coupon.getSendStatus());
			couponMapper.updateById(coupon);
		}
		CouponActive couponActive = new CouponActive();
		couponActive.setCouponId(coupon.getId());
		couponActive.setNum(couponActiveReq.getNum());
		//发放优惠剩余数量
		couponActive.setRemainNum(couponActiveReq.getNum());
		couponActiveMapper.insert(couponActive);
	}

	@Override
	public void setHotCoupon(CouponRecommend couponRecommend) {
		Long couponId = couponRecommend.getCouponId();
		Coupon coupon = couponMapper.selectById(couponId);
		if (coupon == null || !coupon.getDeleted()) {
			throw BusinessRuntimeException.getInstance("该优惠券不存在");
		}
		if (coupon.getHotStatus()) {
			throw BusinessRuntimeException.getInstance("已推荐该优惠券");
		}
		if (!coupon.getHotStatus()) {
			coupon.setHotStatus(!coupon.getHotStatus());
		}
		couponRecommendMapper.insert(couponRecommend);
		couponMapper.updateById(coupon);
	}

	@Override
	public void setPopularizeRelation(CouponDistributeReq couponDistributeReq) {
		Coupon coupon = couponMapper.selectById(couponDistributeReq.getCouponId());
		if (coupon == null || !coupon.getDeleted()) {
			throw BusinessRuntimeException.getInstance("该优惠券不存在");
		}
		CouponDistributePopularize exists = couponDistributePopularizeMapper.selectOne(Wrappers.lambdaQuery(CouponDistributePopularize.class).eq(CouponDistributePopularize::getCouponId, coupon.getId()).eq(CouponDistributePopularize::getDistributeId, couponDistributeReq.getDistributeId()).eq(CouponDistributePopularize::getDeleted, true).last("limit 1"));
		if (exists != null) {
			throw BusinessRuntimeException.getInstance("该优惠券已关联该固定推广者");
		}
		CouponDistributePopularize couponDistributePopularize = new CouponDistributePopularize();
		couponDistributePopularize.setCouponId(coupon.getId());
		couponDistributePopularize.setDistributeId(couponDistributeReq.getDistributeId());
		couponDistributePopularizeMapper.insert(couponDistributePopularize);
	}

	@Override
	public void setPopularizeRelationCode(CouponDistributePopularize couponDistributePopularize) {
		if (couponDistributePopularize.getId() == null || couponDistributePopularize.getId() < 1) {
			throw BusinessRuntimeException.getInstance("优惠券推广者关联id为空");
		}
		CouponDistributePopularize entity = couponDistributePopularizeMapper.selectById(couponDistributePopularize.getId());
		if (entity == null || !entity.getDeleted()) {
			throw BusinessRuntimeException.getInstance("该优惠券推广关联记录不存在");
		}
		if (StrUtil.isEmpty(couponDistributePopularize.getExCode())) {
			throw BusinessRuntimeException.getInstance("优惠券兑换码为空");
		}
		entity.setExCode(couponDistributePopularize.getExCode());
		CouponDistributePopularize exists = couponDistributePopularizeMapper.selectOne(Wrappers.lambdaQuery(CouponDistributePopularize.class).eq(CouponDistributePopularize::getExCode, couponDistributePopularize.getExCode()).eq(CouponDistributePopularize::getDeleted, true).ne(CouponDistributePopularize::getId, entity.getId()).select(CouponDistributePopularize::getId).last("limit 1"));
		if (exists != null) {
			throw BusinessRuntimeException.getInstance("推荐官兑换码不能重复");
		} else {
			Coupon coupon = couponMapper.selectOne(Wrappers.lambdaQuery(Coupon.class).eq(Coupon::getExCode, couponDistributePopularize.getExCode()).eq(Coupon::getDeleted, true).select(Coupon::getId).last("limit 1"));
			if (coupon != null) {
				throw BusinessRuntimeException.getInstance("推荐官兑换码与优惠券兑换码设置重复");
			}
		}
		couponDistributePopularizeMapper.updateById(entity);
	}

	@Override
	public void corpSendCoupon(String unionid, Long couponId) throws Exception {
		User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class).eq(User::getUnionid, unionid).select(User::getId).last("limit 1"));
		if (user == null) {
			throw BusinessRuntimeException.getInstance("该用户未在银河录像注册");
		}
		Coupon coupon = couponMapper.selectById(couponId);
		if (coupon == null || !coupon.getDeleted()) {
			throw BusinessRuntimeException.getInstance("该优惠券已被删除");
		}
		//发放优惠券给用户
		this.sendCouponToUser(user.getId(), couponId, null, null, null, CouponUser.Channel.wxCorp);
	}

	@Override
	public Boolean sendCouponToUser(Long userId, Long couponId, Long couponActiveId, Long recommendId, Long popularizeId, CouponUser.Channel channel) {
		Coupon coupon = couponMapper.selectById(couponId);
		if (coupon == null) {
			return false;
		}
		CouponUser couponUser = couponUserMapper.selectOne(Wrappers.lambdaQuery(CouponUser.class).eq(CouponUser::getUserId, userId).eq(CouponUser::getCouponId, couponId).last("limit 1"));
		if (couponUser == null) {
			couponUser = new CouponUser();
			couponUser.setUserId(userId);
			couponUser.setCouponId(couponId);
			//领券中心
			couponUser.setChannel(channel);
			couponUser.setStatus(CouponUser.Status.unused);
			couponUser.setCouponActiveId(couponActiveId);
			couponUser.setRecommendId(recommendId);
			couponUser.setPopularizeId(popularizeId);
			//优惠券有效时间
			couponFontService.updateCouponUserValidTime(couponId, couponUser);
			try {
				couponUserMapper.insert(couponUser);
				return true;
			} catch (DuplicateKeyException e) {
				log.info("用户:{}重复领取优惠券{}插入数据错误", userId, couponId);
			}
		}
		return false;
	}

	public void checkCouponParamsAndSaveOrUpdate(Coupon coupon) throws Exception {
		List<Coupon.CouponGoodsSku> goodsSkuList = Jsons.parseList(coupon.getGoodsSkuIds(), Coupon.CouponGoodsSku.class);
		if (goodsSkuList.isEmpty()) {
			throw BusinessRuntimeException.getInstance("所选规格不存在");
		}
		if (coupon.getType() == Coupon.Type.discount) {
			if (coupon.getDiscount() == null || (coupon.getDiscount().compareTo(BigDecimal.ZERO) < 0 && coupon.getDiscount().compareTo(BigDecimal.ZERO) > 0)) {
				throw BusinessRuntimeException.getInstance("请输入正确的折扣");
			}
		}
		if (coupon.getType() == Coupon.Type.reduce) {
			if (coupon.getReduceMoney() == null) {
				throw BusinessRuntimeException.getInstance("请配置其立减金额");
			}

			if (coupon.getGoodsType() == Coupon.GoodsType.virtualGoods) {
				List<Long> skuIds = goodsSkuList.stream().map(Coupon.CouponGoodsSku::getSkuId).collect(Collectors.toList());
				skuIds.forEach(skuId -> {
					GoodsDonSku sku = goodsDonSkuMapper.selectOne(Wrappers.lambdaQuery(GoodsDonSku.class).eq(GoodsDonSku::getId, skuId).select(GoodsDonSku::getPrice).last("limit 1"));
					if (sku == null) {
						throw BusinessRuntimeException.getInstance("所选规格不存在");
					}
					if (coupon.getReduceMoney().compareTo(sku.getPrice()) >= 0) {
						throw BusinessRuntimeException.getInstance("可减金额必须小于规格金额");
					}
				});
			} else {
				List<Long> goodsIds = goodsSkuList.stream().map(Coupon.CouponGoodsSku::getGoodsId).collect(Collectors.toList());
				goodsIds.forEach(goodsId -> {
					BigDecimal price = goodsDonMapper.selectMinPriceSkuByGoodsId(goodsId);
					if (price == null) {
						throw BusinessRuntimeException.getInstance("商品不存在");
					}
					if (coupon.getReduceMoney().compareTo(price) >= 0) {
						throw BusinessRuntimeException.getInstance("可减金额必须小于最小规格金额");
					}
				});
			}
		}
		if (coupon.getIsValidTime() == null) {
			coupon.setIsValidTime(false);
		}
		if (coupon.getIsValidTime()) {
			if (coupon.getValidStartTime() == null || coupon.getValidEndTime() == null || (coupon.getValidStartTime().getTime() > coupon.getValidEndTime().getTime())) {
				throw BusinessRuntimeException.getInstance("请输入正确的有效起始和截止时间");
			}
		} else {
			if (coupon.getValidDays() == null && coupon.getValidHours() == null) {
				throw BusinessRuntimeException.getInstance("请选择对应领取后有效时间");
			}

			if (coupon.getValidDays() != null && coupon.getValidDays() < 0) {
				throw BusinessRuntimeException.getInstance("请输入正确的有效天数");
			}

			if (coupon.getValidHours() != null && coupon.getValidHours() < 0) {
				throw BusinessRuntimeException.getInstance("请输入正确的有效小时");
			}
		}
		if (StrUtil.isNotEmpty(coupon.getExCode())) {
			Coupon exists = couponMapper.selectOne(Wrappers.lambdaQuery(Coupon.class).eq(Coupon::getExCode, coupon.getExCode()).eq(Coupon::getDeleted, true).ne(coupon.getId() != null, Coupon::getId, coupon.getId()).select(Coupon::getId).last("limit 1"));
			if (exists != null) {
				throw BusinessRuntimeException.getInstance("优惠券兑换码重复");
			} else {
				CouponDistributePopularize couponDistributePopularize = couponDistributePopularizeMapper.selectOne(Wrappers.lambdaQuery(CouponDistributePopularize.class).eq(CouponDistributePopularize::getExCode, coupon.getExCode()).eq(CouponDistributePopularize::getDeleted, true).select(CouponDistributePopularize::getId).last("limit 1"));
				if (couponDistributePopularize != null) {
					throw BusinessRuntimeException.getInstance("优惠券兑换码与推广者兑换码设置重复");
				}
			}
		}
		if (coupon.getId() == null) {
			try {
				couponMapper.insert(coupon);
			} catch (DuplicateKeyException e) {
				throw BusinessRuntimeException.getInstance("优惠券名称重复");
			}
			goodsSkuList.forEach(goodsSkuId -> {
				CouponSku couponSku = new CouponSku();
				couponSku.setCouponId(coupon.getId());
				couponSku.setGoodsId(goodsSkuId.getGoodsId());
				couponSku.setSkuId(goodsSkuId.getSkuId());
				couponSkuMapper.insert(couponSku);
			});
		} else {
			try {
				couponMapper.updateById(coupon);
			} catch (DuplicateKeyException e) {
				throw BusinessRuntimeException.getInstance("优惠券名称重复");
			}
			couponSkuMapper.deleteRelationSku(coupon.getId());
			goodsSkuList.forEach(goodsSkuId -> {
				CouponSku couponSku = new CouponSku();
				couponSku.setCouponId(coupon.getId());
				couponSku.setGoodsId(goodsSkuId.getGoodsId());
				couponSku.setSkuId(goodsSkuId.getSkuId());
				couponSkuMapper.insert(couponSku);
			});
		}
	}
}
