package com.cyksj.service.exchange.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cyksj.common.annotation.NoSubmit;
import com.cyksj.common.constant.Constant;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.snowflake.Sequence;
import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
import com.cyksj.common.util.Jsons;
import com.cyksj.common.util.StringUtil;
import com.cyksj.dto.RedisKey;
import com.cyksj.dto.Result;
import com.cyksj.enums.GatewayResponse;
import com.cyksj.mapper.*;
import com.cyksj.mapper.manage.distribute.UserDistributeSharedMapper;
import com.cyksj.mapper.manage.exchange.ExchangeCodeMapper;
import com.cyksj.mapper.market.draw.LuckyDrawRecordMapper;
import com.cyksj.model.entity.*;
import com.cyksj.model.excel.ExcelExchangeCodeData;
import com.cyksj.model.manage.views.GroupsRelationView;
import com.cyksj.model.request.ExchangeCodeReq;
import com.cyksj.model.request.ExchangeCodeTicket;
import com.cyksj.redis.RedisService;
import com.cyksj.service.claude.ClaudeCodeService;
import com.cyksj.service.exchange.ExchangeCodeService;
import com.cyksj.service.relation.GroupRelationFrontService;
import com.cyksj.service.relation.GroupsRelationExpiryRecordService;
import com.cyksj.service.shop.YhShopFrontService;
import com.cyksj.service.user.UserBindRelationService;
import com.ejlchina.searcher.BeanSearcher;
import com.ejlchina.searcher.param.Operator;
import com.ejlchina.searcher.util.MapUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/*
 *项目名: netflix
 *文件名: ExchangeCodeServiceImpl
 *创建者: JavaZou
 *创建时间:2022/11/7 15:41
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ExchangeCodeServiceImpl extends ServiceImpl<ExchangeCodeMapper, ExchangeCode> implements ExchangeCodeService {
	private final GoodsDonMapper goodsDonMapper;

	private final GoodsDonSkuMapper goodsDonSkuMapper;

	private final ExchangeCodeMapper exchangeCodeMapper;

	private final GroupsRelationMapper groupsRelationMapper;

	private final GroupsMapper groupsMapper;

	private final RedisService redisService;

	private static final Sequence SEQUENCE = new Sequence(0);

	private final UserMapper userMapper;

	private final OrderDonMapper orderDonMapper;

	private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();

	private final LuckyDrawRecordMapper luckyDrawRecordMapper;

	private final BeanSearcher beanSearcher;

	private final GroupRelationFrontService groupRelationFrontService;

	private final OrderDiscountPlusPurchaseSkuRelationMapper orderDiscountPlusPurchaseSkuRelationMapper;

	private final GroupsRelationExpiryRecordService groupsRelationExpiryRecordService;

	private final YhShopFrontService yhShopFrontService;

	private final UserDistributeSharedMapper userDistributeSharedMapper;

	private final UserDistributeExchangeCodeMapper userDistributeExchangeCodeMapper;

	private final UserDistributeExchangeCodeUseRecordMapper userDistributeExchangeCodeUseRecordMapper;

	private final UserBindRelationService userBindRelationService;

	private final ClaudeCodeUserMapper claudeCodeUserMapper;

	private final ClaudeCodeService claudeCodeService;

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public List<ExcelExchangeCodeData> createExchangeCode(ExchangeCodeReq exchangeCodeReq) throws Exception {
		String skuIds = exchangeCodeReq.getSkuIds();
		if (StrUtil.isEmpty(skuIds)) {
			throw BusinessRuntimeException.getInstance("请选择对应规格");
		}
		List<Long> skuList = Jsons.parseList(skuIds, Long.class);
		Integer skuCount = goodsDonSkuMapper.selectCount(Wrappers.lambdaQuery(GoodsDonSku.class)
				.in(GoodsDonSku::getId, skuList));
		if (skuCount != skuList.size()) {
			throw BusinessRuntimeException.getInstance("所选规格已被删除");
		}
		String goodsIds = goodsDonSkuMapper.selectGIdsBySkuIds(skuList).toString();
		List<ExcelExchangeCodeData> data = new ArrayList<>(exchangeCodeReq.getNumber());
		GoodsDonSku sku = goodsDonSkuMapper.selectById(skuList.get(0));
		for (int i = 0; i < exchangeCodeReq.getNumber(); i++) {
			StringBuilder sb = new StringBuilder(32);
			sb.append("YH");
			sb.append(getFillByGoodsId(sku.getGoodsId()));
			sb.append(getFillByMonth(sku.getMonths()));
			//随即补充12位随即数,组成20位兑换码
			StringUtil.getRandomStr(sb, 12);
			ExchangeCode exchangeCode = new ExchangeCode();
			exchangeCode.setSkuIds(exchangeCodeReq.getSkuIds());
			exchangeCode.setGoodsIds(goodsIds);
			exchangeCode.setCode(sb.toString());
			exchangeCode.setUseStatus(false);
			exchangeCode.setType(exchangeCodeReq.getType());
			exchangeCode.setOperator(exchangeCodeReq.getOperator());
			exchangeCode.setCodeType(exchangeCodeReq.getCodeType());
			exchangeCodeMapper.insert(exchangeCode);
			ExcelExchangeCodeData excelExchangeCodeData = new ExcelExchangeCodeData();
			BeanUtils.copyProperties(exchangeCode, excelExchangeCodeData);
			String title = goodsDonSkuMapper.selectExchangeTitle(skuList);
			excelExchangeCodeData.setTitle(title);
			excelExchangeCodeData.setUseStatusStr(exchangeCode.getUseStatus() ? "已使用" : "未使用");
			data.add(excelExchangeCodeData);
		}
		return data;
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	@NoSubmit
	public Result<String> getTicketByExchangeCode(ExchangeCodeTicket exchangeCodeTicket, Long userId) throws Exception {
		if (StrUtil.isEmpty(exchangeCodeTicket.getCode())) {
			throw BusinessRuntimeException.getInstance("兑换码有误，请使用正确的兑换码");
		}
		//是渠道兑换码
		String code = exchangeCodeTicket.getCode();
		UserDistributeExchangeCode userDistributeExchangeCode = userDistributeExchangeCodeMapper.selectOne(Wrappers.lambdaQuery(UserDistributeExchangeCode.class)
				.eq(UserDistributeExchangeCode::getCode, code)
				.last("limit 1"));
		if (userDistributeExchangeCode != null) {
			//是否是该渠道下的用户
			Integer bindCount = userDistributeSharedMapper.selectCount(Wrappers.lambdaQuery(UserDistributeShared.class)
					.eq(UserDistributeShared::getSharedId, userDistributeExchangeCode.getUserId())
					.eq(UserDistributeShared::getUserId, userId));
			if (bindCount == 0) {
				throw BusinessRuntimeException.getInstance("您不是该渠道下的分销用户");
			}
			//是否已经兑换过
			Integer useCount = userDistributeExchangeCodeUseRecordMapper.selectCount(Wrappers.lambdaQuery(UserDistributeExchangeCodeUseRecord.class)
					.eq(UserDistributeExchangeCodeUseRecord::getUserId, userId)
					.eq(UserDistributeExchangeCodeUseRecord::getCode, code));
			if (useCount > 0) {
				throw BusinessRuntimeException.getInstance("您已使用该兑换码");
			}

			try {
				UserDistributeExchangeCodeUseRecord userDistributeExchangeCodeUseRecord = new UserDistributeExchangeCodeUseRecord();
				userDistributeExchangeCodeUseRecord.setUserId(userId);
				userDistributeExchangeCodeUseRecord.setCode(code);
				userDistributeExchangeCodeUseRecordMapper.insert(userDistributeExchangeCodeUseRecord);
				log.info("用户userId:{}兑换渠道兑换码:{}", userId, code);
				GoodsDonSku sku = goodsDonSkuMapper.selectById(userDistributeExchangeCode.getSkuId());
				GroupsRelation relation = getRelationNoOrder(sku, userId, 0l);
				//重新设置时间
				DateField dateField = DateField.MONTH;
				if (Constant.DAY_DATE.equals(userDistributeExchangeCode.getTimeType())) {
					dateField = DateField.DAY_OF_YEAR;
				} else if (Constant.HOUR_DAY_OF_DATE.equals(userDistributeExchangeCode.getTimeType())) {
					dateField = DateField.HOUR_OF_DAY;
				}
				relation.setAqType(2);
				relation.setExpiryTime(DateUtil.offset(relation.getStartTime(), dateField, userDistributeExchangeCode.getTime()));
				groupsRelationMapper.updateById(relation);

				userDistributeExchangeCodeUseRecord.setRelationId(relation.getId());
				userDistributeExchangeCodeUseRecordMapper.updateById(userDistributeExchangeCodeUseRecord);
			} catch (DuplicateKeyException e) {
				throw BusinessRuntimeException.getInstance("您已使用该兑换码");
			}
			return GatewayResponse.SUCCESS.newBuilder().toResult();
		}
		ExchangeCode exchangeCode = this.getOne(Wrappers.lambdaQuery(ExchangeCode.class).eq(ExchangeCode::getCode, exchangeCodeTicket.getCode()).last("limit 1"));
		if (exchangeCode == null) {
			throw BusinessRuntimeException.getInstance("兑换码有误，请使用正确的兑换码");
		}
		if (exchangeCode.getUseStatus()) {
			throw BusinessRuntimeException.getInstance("该兑换码已使用");
		}
		//店铺中 进行兑换码 兑换 标记订单 座位
		String customId = exchangeCodeTicket.getCustomId();
		Long yhsId = yhShopFrontService.checkShopCustomIdAndReturnShopId(customId);
		//兑换成功
		exchangeCode.setUseStatus(true);
		exchangeCode.setUserId(userId);
		exchangeCode.setUseTime(DateTime.now());
		int update = exchangeCodeMapper.update(exchangeCode, Wrappers.lambdaQuery(ExchangeCode.class).eq(ExchangeCode::getId, exchangeCode.getId()).eq(ExchangeCode::getUseStatus, false));
		if (update != 1) {
			throw BusinessRuntimeException.getInstance("该兑换码已使用");
		}
		//是否是推广用户未登录订单关联的兑换码
		OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
				.eq(OrderDon::getIsNoLogin, true)
				.eq(OrderDon::getExCode, exchangeCode.getCode())
				.notIn(OrderDon::getStatus, Constant.noOrderStatus)
				.last("limit 1"));
//		Long popularizeId = orderDon.getPopularizeId();
//
//		//360 渠道兑换规则验证.
//		if(popularizeId != null && popularizeId != 0){
//			String channel = channelPopularizeMapper.selectChannelByPid(popularizeId);
//			if (Constant.CHANNEL_NAME_360.equals(channel)) {
//				//查询该用户之前是否存在订单.
//				Integer count = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
//						.eq(OrderDon::getUserId, userId)
//						.notIn(OrderDon::getStatus, Constant.noOrderStatus));
//				if (count > 0) {
//					throw new BusinessRuntimeException("您不符合360活动条件.");
//				}
//			}
//		}

		if (orderDon != null && orderDon.getStatus() == OrderDon.Status.refund) {
			throw BusinessRuntimeException.getInstance("您的订单已退款,无法使用该兑换码");
		}
		List<Long> skuIds = Jsons.parseList(exchangeCode.getSkuIds(), Long.class);
		skuIds.forEach(skuId -> {
			getGroupTripsTicket(yhsId, goodsDonSkuMapper.selectById(skuId), userId, orderDon, OrderDon.Type.EX_CODE, exchangeCodeTicket.getCode());
		});
		//生成车票订单
		log.info("用户:{}通过兑换码:{}兑换成功", userId, exchangeCodeTicket.getCode());
		if (exchangeCode.getType() == 1) {
			luckyDrawRecordMapper.updateExCodeStatus(userId, exchangeCode.getCode());
		}
		return GatewayResponse.SUCCESS.newBuilder().toResult("兑换成功");
	}

	@Override
	public String getExCode(Long goodsId, Long skuId, Integer type) {
		ExchangeCodeReq exchangeCodeReq = new ExchangeCodeReq();
		exchangeCodeReq.setNumber(1);
//		exchangeCodeReq.setGoodsId(goodsId);
		exchangeCodeReq.setSkuIds(List.of(skuId).toString());
		//兑换码
		exchangeCodeReq.setCodeType(1);
		if (type != null) {
			exchangeCodeReq.setType(type);
		}
		try {
			List<ExcelExchangeCodeData> exchangeCodes = this.createExchangeCode(exchangeCodeReq);
			return exchangeCodes.get(0).getCode();
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 根据平台id获取填充的字符串
	 */
	private String getFillByGoodsId(Long goodsId) {
		String goodsIdStr = String.valueOf(goodsId);
		if (goodsIdStr.length() == 1) {
			return String.format("%s%s%s", 0, 0, goodsId);
		}
		if (goodsIdStr.length() == 2) {
			return String.format("%s%s", 0, goodsId);
		}
		//最大不超过999
		if (goodsIdStr.length() > 3) {
			return goodsIdStr.substring(0, 3);
		}
		return goodsIdStr;
	}

	/**
	 * 根据月份长度获取填充的字符串
	 */
	private String getFillByMonth(Integer skuMonth) {
		String goodsIdStr = String.valueOf(skuMonth);
		if (goodsIdStr.length() == 1) {
			return String.format("%s%s%s", 0, 0, skuMonth);
		}
		return String.format("%s%s", 0, skuMonth);
	}

	/**
	 * 获取车位
	 */
	@Override
	public GroupsRelation getGroupTripsTicket(Long yhsId, GoodsDonSku sku, Long userId, OrderDon exCodeOrderDon, OrderDon.Type orderDonTye, String exCode) {
		if (sku == null) {
			throw BusinessRuntimeException.getInstance("规格不存在,请联系客服");
		}
		GoodsDon goodsDon = goodsDonMapper.selectById(sku.getGoodsId());
		if (goodsDon == null) {
			throw BusinessRuntimeException.getInstance("平台不存在,请联系客服");
		}
		User user = userMapper.selectById(userId);
		if (user == null) {
			throw BusinessRuntimeException.getInstance("用户不存在");
		}
		GroupsRelation relation = getRelationNoOrder(sku, userId, yhsId);

		Long relationId = relation.getId();
		OrderDon orderDon;
		if (exCodeOrderDon != null) {
			orderDon = exCodeOrderDon;
			orderDon.setRelationId(relationId);
			orderDon.setUserId(userId);
			orderDon.setStatus(goodsDon.getType() == 1 && goodsDon.getSecondType() == 2 ? OrderDon.Status.complete : OrderDon.Status.hasPayment);
			orderDon.setYhsId(yhsId);
			orderDonMapper.updateById(orderDon);
			if (orderDon.getIsDp()) {
				//是否已经发送优惠加购车票
				OrderDiscountPlusPurchaseSkuRelation purchaseSkuRelation = orderDiscountPlusPurchaseSkuRelationMapper.selectOne(Wrappers.lambdaQuery(OrderDiscountPlusPurchaseSkuRelation.class)
						.eq(OrderDiscountPlusPurchaseSkuRelation::getOrderId, orderDon.getId()));
				if (purchaseSkuRelation != null) {
					String plusSkuIdsStr = purchaseSkuRelation.getPlusSkuIds();
					String relationIdsStr = purchaseSkuRelation.getRelationIds();
					if (StrUtil.isNotEmpty(plusSkuIdsStr) && StrUtil.isEmpty(relationIdsStr)) {
						try {
							List<Long> plusSkuIds = Jsons.parseList(plusSkuIdsStr, Long.class);
							//发送优惠加购 规格车票
							List<Long> dis_relation_ids = new ArrayList<>();
							plusSkuIds.forEach(plus_skuId -> {
								GoodsDonSku plus_sku = goodsDonSkuMapper.selectById(plus_skuId);
								if (plus_sku == null) {
									log.error("订单id:{}优惠加购规格已被删除 skuId:{},车票未发送", orderDon.getId(), plus_skuId);
									return;
								}
								GroupsRelation relationNoOrder = getRelationNoOrder(plus_sku, orderDon.getUserId(), orderDon.getYhsId());
								dis_relation_ids.add(relationNoOrder.getId());
							});
							//保存订单关联优惠加购车票
							orderDiscountPlusPurchaseSkuRelationMapper.update(null, Wrappers.lambdaUpdate(OrderDiscountPlusPurchaseSkuRelation.class)
									.set(OrderDiscountPlusPurchaseSkuRelation::getRelationIds, dis_relation_ids.toString())
									.eq(OrderDiscountPlusPurchaseSkuRelation::getOrderId, orderDon.getId())
									.isNull(OrderDiscountPlusPurchaseSkuRelation::getRelationIds));
						} catch (Exception e) {
						}
					}
				}
			}
		} else {
			/* 生成订单 */
			String donNo = SEQUENCE.nextId().toString();
			orderDon = new OrderDon();
			orderDon.setOrderNo(donNo);
			orderDon.setOpenId(user.getOpenId());
			orderDon.setMoney(BigDecimal.ZERO);
			orderDon.setSkuId(sku.getId());
			orderDon.setRelationId(relationId);
			orderDon.setYhsId(yhsId);
			//默认数量为1
			orderDon.setNum(1);
			orderDon.setGoodsId(sku.getGoodsId());
			orderDon.setExCode(exCode);
			orderDon.setStatus(goodsDon.getType() == 1 && goodsDon.getSecondType() == 2 ? OrderDon.Status.complete : OrderDon.Status.hasPayment);
			if (relation.getStartTime() == null || relation.getExpiryTime() == null) {
				orderDon.setStatus(OrderDon.Status.hasPayment);
			}
			if (relation != null && relation.getStatus() == GroupsRelation.Status.outside) {
				orderDon.setIsOt(true);
			}
			//兑换码兑换
			orderDon.setType(orderDonTye);
			orderDon.setUserId(user.getId());
			StringBuilder payTitle = new StringBuilder();
			payTitle.append(goodsDon.getTitle());
			payTitle.append(sku.getSpecVal());
			orderDon.setPayTitle(payTitle.toString());
			orderDonMapper.insert(orderDon);
			log.info("用户{}兑换规格:{}车位成功", user.getId(), orderDon.getSkuId());

			if (relation.getIsClaudeCodeRenew() != null && relation.getIsClaudeCodeRenew()) {
				//claude code续费
				orderDon.setOrderType(2);
				orderDonMapper.updateById(orderDon);
				//续费且升级
				if (relation.getIsClaudeCodeUpgrade() != null && relation.getIsClaudeCodeUpgrade()) {
					claudeCodeService.handleClaudeCodeUserPackageSku(relation, sku, orderDon.getId());
				}
			}
		}
		if (orderDonTye == OrderDon.Type.EX_CODE) {
			//同步车票是否重购 记录
			TASK_POOL.execute(() -> {
				groupsRelationExpiryRecordService.syncGroupsRelationExpiryRecord(orderDon, goodsDon, sku);
			});
		}
		relation.setOrderId(orderDon.getId());
		//邀请制代充平台
		if ((goodsDon.getSpecialType() != null && goodsDon.getSpecialType() == GoodsDon.SpecialType.recharge) || Constant.RECHARGE_INVITE_GOODS_IDS.contains(goodsDon.getId())) {
			relation.setStartTime(null);
			relation.setExpiryTime(null);
			relation.setRechargeStatus(GroupsRelation.RechargeStatus.waiting);
			relation.setSubmitTime(DateTime.now());
			//GPT代充
			if (goodsDon.getId() == Constant.GPT_RECHARGE_GOODS_ID) {
				//代充次数
				relation.setRechargeNum(sku.getMonths());
				relation.setRechargeRemainNum(relation.getRechargeNum());
			}
			groupsRelationMapper.updateById(relation);
		}
		return relation;
	}

	@Override
	public GroupsRelation getRelationNoOrder(GoodsDonSku sku, Long userId, Long yhsId) {
		//claude code商品兑换
		if (sku.getGoodsId() == Constant.CLAUDE_CODE_GOODS_ID) {
			List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
			GroupsRelationView groupsRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder().field(GroupsRelationView::getUserId, userIdList).op(Operator.InList).field(GroupsRelationView::getGoodsId, Constant.CLAUDE_CODE_GOODS_ID).field(GroupsRelationView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan).build());
			if (groupsRelationView != null) {
				GoodsDonSku relationSku = goodsDonSkuMapper.selectById(groupsRelationView.getSkuId());
				//兑换的规格 低于当前规格 不让兑换
				if (relationSku.getClaudeDailyLimit() > sku.getClaudeDailyLimit()) {
					throw BusinessRuntimeException.getInstance("请在claude code当前版本过期后再兑换");
				}
				Date expiryTime = groupsRelationView.getExpiryTime();
				if (sku.getDays() != null) {
					expiryTime = DateUtil.offsetDay(expiryTime, sku.getDays());
				} else {
					expiryTime = DateUtil.offsetMonth(expiryTime, sku.getMonths());
				}
				GroupsRelation relation = groupsRelationMapper.selectById(groupsRelationView.getId());
				relation.setExpiryTime(expiryTime);
				groupsRelationMapper.updateById(relation);
				//同规格只加时长
				relation.setIsClaudeCodeRenew(Boolean.TRUE);
				if (relationSku.getClaudeDailyLimit() != sku.getClaudeDailyLimit()) {
					relation.setIsClaudeCodeUpgrade(true);
				}
				return relation;
			}
		}
		Integer retryNum = 1;
		List<Long> errorsRelationIds = new ArrayList<>();
		GroupsRelation relation = getFinalRelation(sku, userId, retryNum, yhsId, errorsRelationIds);
		return relation;
	}

	public GroupsRelation getFinalRelation(GoodsDonSku sku, Long userId, Integer retryNum, Long yhsId, List<Long> errorsRelationIds) {
		//获取车票车位
		GroupsRelation relation = groupRelationFrontService.getRelation(null, userId, sku, null);

		try {
			//锁定座位
			setRelation(relation);
			relation.setUserId(userId);
			GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
			if (GroupsTrips.Status.validity.equals(groupsTrips.getStatus())) {
				//如果续费增加时间，如果首次则设置当前时间为初始时间
				Date expiryTime = Optional.ofNullable(relation.getExpiryTime()).orElse(new Date());
				Date newDate;
				if (sku.getDays() != null && sku.getDays() > 0) {
					newDate = DateUtil.offsetDay(expiryTime, sku.getDays() * 1);
				} else {
					//奈飞月付 按30天计算
					if (sku.getId() == 4) {
						newDate = DateUtil.offsetDay(expiryTime, 30);
					} else {
						newDate = DateUtil.offset(expiryTime, DateField.MONTH, sku.getMonths() * 1);
					}
				}
				relation.setExpiryTime(newDate);
				relation.setStartTime(relation.getStartTime() == null ? new Date() : null);
			}
			if (relation.getStatus() != GroupsRelation.Status.outside) {
				relation.setStatus(GroupsRelation.Status.validity);
			}
			relation.setYhsId(yhsId);
			if (yhsId != null && yhsId != 0) {
				relation.setCmt(1);
			}
			groupsRelationMapper.updateById(relation);

			Long skuId = sku.getId();
			Long groupsId = relation.getGroupsId();
			//校验指定平台规格的 目前车队的可停车位数
			groupRelationFrontService.checkGroupsAvailParkingNum(skuId, groupsId, relation.getGroupsAvailParkingNum(), relation.getMaxNum());

			groupRelationFrontService.adjustGroupsParkingTime(relation.getId(), sku);
		} catch (Exception e) {
			//删除座位缓存
			delRelationKey(relation.getId(), userId);
			errorsRelationIds.add(relation.getId());
			if (retryNum == 15) {
				log.error("用户:{}获取车票:{}异常", userId, relation.getId());
				throw BusinessRuntimeException.getInstance("获取车票异常,请联系客服");
			}
			//失败重新给他分配车位
			return getFinalRelation(sku, userId, ++retryNum, yhsId, errorsRelationIds);
		}
		return relation;
	}

	public void setRelation(GroupsRelation relation) {
		Long relationId = relation.getId();
		Long userId = relation.getUserId();
		Long groupsId = relation.getGroupsId();
		GroupsRelation.Status status = relation.getStatus();
		String relation_num_key = RedisKey.GROUPS_RELATION_NUM_KEY + relationId;
		if (!redisService.setNx(relation_num_key, userId, 60 * 5L)) {
			GroupsRelation dbRelation = groupsRelationMapper.selectById(relationId);
			if (dbRelation.getUserId() != 0) {
				log.info("=====>用户:{}未抢到座位:{}", userId, relationId);
				throw new BusinessRuntimeException("系统繁忙，请重试...");
			}
		}
		if (status == GroupsRelation.Status.outside) {
			return;
		}
		int count = groupsMapper.decrAvailableNum(groupsId);
		if (count == 0) {
			log.error("车位异常 groupId:{}", groupsId);
			groupsMapper.updateAvailableNum(groupsId);
			//删除座位缓存
			delRelationKey(relationId, userId);
			throw new BusinessRuntimeException("车位异常");
		}
	}

	/**
	 * 清除座位缓存key
	 */
	public void delRelationKey(Long relationId, Long userId) {
		String relation_num_key = RedisKey.GROUPS_RELATION_NUM_KEY + relationId;
		Object object = redisService.get(relation_num_key);
		if (object != null) {
			try {
				Long keyUserId = Long.parseLong(object.toString());
				//清除车票key
				if (ObjectUtil.equal(userId, keyUserId)) {
					redisService.del(relation_num_key);
				}
			} catch (Exception e) {
				log.error("删除缓存key错误:{}", StringUtil.getErrorText(e));
			}
		}
	}
}
