package com.cyksj.service.market.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyksj.common.constant.Constant;
import com.cyksj.common.constant.PointsRecordConst;
import com.cyksj.common.constant.TaskTypeEnum;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.snowflake.Sequence;
import com.cyksj.common.util.Jsons;
import com.cyksj.mapper.*;
import com.cyksj.mapper.corp.CorpUserMapper;
import com.cyksj.mapper.manage.coupon.CouponUserMapper;
import com.cyksj.mapper.manage.distribute.UserDistributeSharedMapper;
import com.cyksj.mapper.market.draw.LuckyDrawRecordMapper;
import com.cyksj.mapper.market.draw.LuckyDrawSpecificChanceMapper;
import com.cyksj.mapper.market.draw.LuckyDrawSpecificChanceRecordMapper;
import com.cyksj.mapper.market.sign.SignConfigMapper;
import com.cyksj.mapper.market.sign.SignUserMapper;
import com.cyksj.mapper.market.task.TaskFollowPlatVerifyMapper;
import com.cyksj.mapper.market.task.TaskUserCompleteRecordMapper;
import com.cyksj.mapper.market.task.UserBindDetailMapper;
import com.cyksj.model.entity.*;
import com.cyksj.model.manage.views.GroupsRelationView;
import com.cyksj.model.request.LuckyDrawReq;
import com.cyksj.model.request.TaskFollowReq;
import com.cyksj.model.views.LuckyDrawView;
import com.cyksj.model.views.TaskFrontView;
import com.cyksj.redis.RedisService;
import com.cyksj.service.coin.UserGalaxyCoinService;
import com.cyksj.service.exchange.ExchangeCodeService;
import com.cyksj.service.mange.coupon.CouponCommonService;
import com.cyksj.service.market.MarketFrontService;
import com.cyksj.service.relation.GroupRelationFrontService;
import com.cyksj.service.sys.SysConfigService;
import com.ejlchina.searcher.BeanSearcher;
import com.ejlchina.searcher.param.Operator;
import com.ejlchina.searcher.util.MapBuilder;
import com.ejlchina.searcher.util.MapUtils;
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.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

@Service
@RequiredArgsConstructor
@Slf4j
public class MarketFrontServiceImpl implements MarketFrontService {
	private final SignUserMapper signUserMapper;

	private final SignConfigMapper signConfigMapper;

	private final SysConfigService sysConfigService;

	private final UserMapper userMapper;

	private final BeanSearcher beanSearcher;

	private final CouponCommonService couponCommonService;

	private final CouponUserMapper couponUserMapper;

	private final ExchangeCodeService exchangeCodeService;

	private final LuckyDrawRecordMapper luckyDrawRecordMapper;

	private final OrderDonMapper orderDonMapper;

	private final AddressMapper addressMapper;

	private final OrderDonTransportMapper orderDonTransportMapper;

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

	private final CorpUserMapper corpUserMapper;

	private final TaskUserCompleteRecordMapper taskUserCompleteRecordMapper;

	private final UserDistributeSharedMapper userDistributeSharedMapper;

	private final UserBindDetailMapper UserBindDetailMapper;

	private final RedisService redisService;

	private final TaskFollowPlatVerifyMapper taskFollowPlatVerifyMapper;

	private final GroupsRelationMapper groupsRelationMapper;

	private final LuckyDrawSpecificChanceMapper luckyDrawSpecificChanceMapper;

	private final LuckyDrawSpecificChanceRecordMapper luckyDrawSpecificChanceRecordMapper;

	private final GroupRelationFrontService groupRelationFrontService;

	private final UserGalaxyCoinService userGalaxyCoinService;

	@Override
	public SignUser signByUserId(Long userId) {
		//第一次签到
		SignUser signUser = signUserMapper.selectOne(Wrappers.lambdaQuery(SignUser.class)
				.eq(SignUser::getUserId, userId).last("limit 1"));
		if (signUser == null) {
			log.info("用户:{}第一次签到", userId);
			signUser = new SignUser();
			signUser.setUserId(userId);
			signUser.setDay(1);
			signUser.setDayPeriod(1);
			try {
				signUserMapper.insert(signUser);
				//发放积分
				updateUserSignDay(signUser, true);
				signUser.setIsHadChecked(true);
			} catch (DuplicateKeyException e) {
				log.info("用户:{}重复签到记录插入", userId);
			}
		}else {
			//更新签到
			signCheck(signUser);
		}
		SignUser sign = signUserMapper.selectOne(Wrappers.lambdaQuery(SignUser.class)
				.eq(SignUser::getUserId, userId).last("limit 1"));
		sign.setPoints(signUser.getPoints());
		sign.setIsHadChecked(signUser.getIsHadChecked());
		return sign;
	}

	@Override
	public SignUser getUserSignDetail(Long userId) {
		SignUser signUser = signUserMapper.selectOne(Wrappers.lambdaQuery(SignUser.class)
				.eq(SignUser::getUserId, userId).last("limit 1"));
		if (signUser == null) {
			signUser = new SignUser();
			signUser.setUserId(userId);
			signUser.setDay(0);
			signUser.setDayPeriod(0);
			signUser.setIsHadChecked(false);
			return signUser;
		}
		Date updateTime = signUser.getUpdateTime();
		DateTime signZero = DateUtil.beginOfDay(updateTime);
		DateTime thisZero = DateUtil.beginOfDay(DateTime.now());
		if (updateTime.getTime() < thisZero.getTime()) {
			if (thisZero.getTime() - signZero.getTime() != Constant.DAY_MILLS) {
				log.info("用户:{}断签,断签天数为:{}", signUser.getUserId(), signUser.getDayPeriod());
				signUser.setDay(0);
				signUser.setDayPeriod(0);
			}
			signUser.setIsHadChecked(false);
		} else {
			signUser.setIsHadChecked(true);
		}
		return signUser;
	}


	@Override
	@Transactional(rollbackFor = Throwable.class)
	public LuckyDrawView lottery(Long userId, LuckyDraw.DrawType drawType) throws Exception {
		List<Long> goodsIdList = null;
		if (drawType == LuckyDraw.DrawType.normal) {
			luckyDrawNormalCheck(userId);
		} else {
			goodsIdList = luckyDrawSpecificCheck(userId);
		}
		List<LuckyDrawView> drawViews = beanSearcher.searchAll(LuckyDrawView.class, MapUtils.builder()
				.field(LuckyDrawView::getStatus, true).op(Operator.Equal)
				.field(LuckyDrawView::getDrawType, drawType.name())
				.orderBy(LuckyDrawView::getProbability).asc()
				.build());
		if (drawViews.isEmpty()) {
			throw BusinessRuntimeException.getInstance("暂未配置奖品");
		}
		Integer index = randomProbabilityIndex(drawViews);
		if (index == -1) {
			throw BusinessRuntimeException.getInstance("系统异常,请刷新页面重新操作");
		}
		LuckyDrawView luckyDraw = drawViews.get(index);
		if (luckyDraw.getType() != LuckyDraw.Type.points && luckyDraw.getType() != LuckyDraw.Type.duration) {
			Integer num = 1;
			luckyDraw = randomNum(luckyDraw, drawViews, num, userId);
			if (luckyDraw == null) {
				//随机给一份爱心值谢谢惠顾奖品
				List<LuckyDrawView> others = beanSearcher.searchAll(LuckyDrawView.class, MapUtils.builder()
						.field(LuckyDrawView::getStatus, true).op(Operator.Equal)
						.field(LuckyDrawView::getType, LuckyDraw.Type.points.name()).op(Operator.Equal)
						.build());
				Integer finalIndex = randomProbabilityIndex(others);
				luckyDraw = others.get(finalIndex);
			}
		}
		LuckyDrawRecord record = new LuckyDrawRecord();
		BeanUtil.copyProperties(luckyDraw, record, "status");
		if (luckyDraw.getType() == LuckyDraw.Type.points) {
			userGalaxyCoinService.sendGalaxyCoinRecord(userId, luckyDraw.getPoints(), PointsRecordConst.LOTTERY, false);
			record.setStatus(LuckyDrawRecord.Status.success);
		} else if (luckyDraw.getType() == LuckyDraw.Type.coupon) {
			//发放优惠券
			couponCommonService.sendCouponToUser(userId, luckyDraw.getCouponId(), null, null, null, CouponUser.Channel.lottery);
			record.setStatus(LuckyDrawRecord.Status.success);
		} else if (luckyDraw.getType() == LuckyDraw.Type.virtualGoods) {
			record.setExCode(exchangeCodeService.getExCode(luckyDraw.getGoodsId(), luckyDraw.getSkuId(), 1));
			record.setStatus(LuckyDrawRecord.Status.pending);
		} else if (luckyDraw.getType() == LuckyDraw.Type.realGoods) {
			record.setStatus(LuckyDrawRecord.Status.pending);
		} else if (luckyDraw.getType() == LuckyDraw.Type.duration) {
			MapBuilder builder = MapUtils.builder()
					.field(GroupsRelationView::getUserId, userId)
					.field(GroupsRelationView::getGoodsType, 1)
					.field(GroupsRelationView::getGoodsSecondType, 2)
					.field(GroupsRelationView::getStatus, "validity")
					.field(GroupsRelationView::getExpiryTime).op(Operator.NotNull);
			//特定奖池不选择时,默认查询所有非邀请制平台车票
			if (goodsIdList != null && goodsIdList.size() > 0) {
				builder.field(GroupsRelationView::getGoodsId, goodsIdList).op(Operator.InList);
			}
			//若对应平台车票仅有一张且已发车,直接增加车票时长
			List<GroupsRelationView> relations = beanSearcher.searchAll(GroupsRelationView.class, builder.build());
			if (relations != null && relations.size() == 1) {
				Long relationId = relations.get(0).getId();
				updateRelationExpiryTime(userId, relationId, luckyDraw.getDays());
				record.setStatus(LuckyDrawRecord.Status.success);
			} else {
				record.setStatus(LuckyDrawRecord.Status.pending);
			}
		}
		record.setUserId(userId);
		record.setDrawId(luckyDraw.getId());
		luckyDrawRecordMapper.insert(record);
		luckyDraw.setRecordId(record.getId());
		return luckyDraw;
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void receivedLuckyDraw(Long userId, LuckyDrawReq luckyDrawReq) {
		LuckyDrawRecord record = luckyDrawRecordMapper.selectOne(Wrappers.lambdaQuery(LuckyDrawRecord.class)
				.eq(LuckyDrawRecord::getId, luckyDrawReq.getRecordId())
				.eq(LuckyDrawRecord::getUserId, userId).last("limit 1"));
		if (record == null) {
			throw BusinessRuntimeException.getInstance("该中奖奖品不存在");
		}
		if (record.getStatus() == LuckyDrawRecord.Status.success) {
			throw BusinessRuntimeException.getInstance("您已领取该中奖奖品");
		}
		Long orderId = null;
		if (record.getType() == LuckyDraw.Type.realGoods) {
			orderId = receiveRealGoodsReward(userId, record, luckyDrawReq.getAddressId());
		} else if (record.getType() == LuckyDraw.Type.duration) {
			updateRelationExpiryTime(userId, luckyDrawReq.getRelationId(), record.getDays());
		}
		if (orderId == null) {
			orderId = 0l;;
		}
		Integer update = luckyDrawRecordMapper.updateStatus(record.getId(), orderId, LuckyDrawRecord.Status.success);
		if (update != 1) {
			throw BusinessRuntimeException.getInstance("系统异常,请刷新页面重新操作");
		}
	}

	@Override
	public void updateTaskStatus(TaskFrontView data, Long userId) {
		this.checkTaskStatus(data, userId);
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void receivedTaskPoints(Long userId, Long taskId) {
		String key = RedisService.key.TASK_RECEIVED_KEY.getNameFormat(userId, taskId);
		if (!redisService.setNx(key, taskId, RedisService.key.TASK_RECEIVED_KEY.getTimeout())) {
			throw BusinessRuntimeException.getInstance("请勿重复点击按钮,正在领取中...");
		}
		TaskFrontView data = beanSearcher.searchFirst(TaskFrontView.class, MapUtils.builder()
				.field(TaskFrontView::getId, taskId).build());
		if (data == null) {
			throw BusinessRuntimeException.getInstance("该任务不存在");
		}
		this.checkTaskStatus(data, userId);
		if (data.getStatus() == TaskUserCompleteRecord.Status.waiting) {
			throw BusinessRuntimeException.getInstance("您未完成该任务");
		}
		if (data.getStatus() == TaskUserCompleteRecord.Status.received) {
			throw BusinessRuntimeException.getInstance("您已领取该任务奖励");
		}
		if (data.getCouponId() != null && data.getCouponId() != 0) {
			couponCommonService.sendCouponToUser(userId, data.getCouponId(), null, null, null, CouponUser.Channel.task);
		}
		userGalaxyCoinService.sendGalaxyCoinRecord(userId, data.getPoints(), PointsRecordConst.TASK, false);
		//改变状态
		TaskUserCompleteRecord record = new TaskUserCompleteRecord();
		record.setId(data.getTaskCompleteRecordId());
		record.setStatus(TaskUserCompleteRecord.Status.received);
		taskUserCompleteRecordMapper.updateById(record);
		redisService.del(key);
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void toCompleteFollowTask(TaskFollowReq taskFollowReq) {
		Long taskId = taskFollowReq.getTaskId();
		Long userId = taskFollowReq.getUserId();
		TaskFrontView data = beanSearcher.searchFirst(TaskFrontView.class, MapUtils.builder()
				.field(TaskFrontView::getId, taskId).build());
		//非审核
		if (!data.getIsVerify()) {
			throw BusinessRuntimeException.getInstance("");
		}
		TaskFollowPlatVerify taskFollowPlatVerify = new TaskFollowPlatVerify();
		taskFollowPlatVerify.setTaskId(taskId);
		taskFollowPlatVerify.setUserId(userId);
		taskFollowPlatVerify.setPlatNickname(taskFollowReq.getPlatNickname());
		taskFollowPlatVerify.setImg(taskFollowReq.getImg());
		taskFollowPlatVerify.setLink(taskFollowReq.getLink());
		try {
			taskFollowPlatVerifyMapper.insert(taskFollowPlatVerify);
			TaskUserCompleteRecord record = new TaskUserCompleteRecord();
			record.setTaskId(taskId);
			record.setUserId(userId);
			record.setPoints(data.getPoints());
			record.setStatus(TaskUserCompleteRecord.Status.verifying);
			taskUserCompleteRecordMapper.insert(record);
		} catch (DuplicateKeyException e) {

		}
	}

	@Override
	public void updateFailFollowTask(TaskFollowReq taskFollowReq) {
		if (taskFollowReq.getId() == null || taskFollowReq.getId() < 1) {
			throw BusinessRuntimeException.getInstance("");
		}
		TaskFollowPlatVerify dbTaskFollowPlatVerify = taskFollowPlatVerifyMapper.selectById(taskFollowReq.getId());
		if (dbTaskFollowPlatVerify == null) {
			throw BusinessRuntimeException.getInstance("该提交记录不存在");
		}
		if (dbTaskFollowPlatVerify.getStatus() == TaskFollowPlatVerify.Status.success) {
			throw BusinessRuntimeException.getInstance("您提交的记录已审核成功");
		}
		dbTaskFollowPlatVerify.setPlatNickname(taskFollowReq.getPlatNickname());
		dbTaskFollowPlatVerify.setStatus(TaskFollowPlatVerify.Status.verifying);
		dbTaskFollowPlatVerify.setImg(taskFollowReq.getImg());
		taskFollowPlatVerifyMapper.updateById(dbTaskFollowPlatVerify);

		TaskUserCompleteRecord record = taskUserCompleteRecordMapper.selectOne(Wrappers.lambdaQuery(TaskUserCompleteRecord.class)
				.eq(TaskUserCompleteRecord::getUserId, dbTaskFollowPlatVerify.getUserId())
				.eq(TaskUserCompleteRecord::getTaskId, dbTaskFollowPlatVerify.getTaskId())
				.last("limit 1"));
		if (record != null) {
			record.setStatus(TaskUserCompleteRecord.Status.verifying);
			taskUserCompleteRecordMapper.updateById(record);
		}
	}

	/**
	 * 更新签到时间
	 */
	public void signCheck(SignUser signUser) {
		//更新时间是否小于今日零时且是否为连签
		Date updateTime = signUser.getUpdateTime();
		DateTime signZero = DateUtil.beginOfDay(updateTime);
		DateTime thisZero = DateUtil.beginOfDay(DateTime.now());
		if (updateTime.getTime() >= thisZero.getTime()) {
			signUser.setIsHadChecked(true);
//            throw BusinessRuntimeException.getInstance("您已签到");
		} else {
			if (updateTime.before(thisZero) && thisZero.getTime() - signZero.getTime() == Constant.DAY_MILLS) {
				log.info("用户:{}连续签到,此时天数为:{}", signUser.getUserId(), signUser.getDayPeriod());
				signUser.setDay(signUser.getDay() + 1);
				if (signUser.getDayPeriod() == 7) {
					signUser.setDayPeriod(0);
				}
				signUser.setDayPeriod(signUser.getDayPeriod() + 1);
				//更新签到时间
				updateUserSignDay(signUser, false);
				signUser.setIsHadChecked(true);
			} else {
				log.info("用户:{}断签,断签天数为:{}", signUser.getUserId(), signUser.getDayPeriod());
				signUser.setDay(1);
				signUser.setDayPeriod(1);
				//更新签到时间
				updateUserSignDay(signUser, false);
				signUser.setIsHadChecked(true);
			}
		}
	}

	public void updateUserSignDay(SignUser signUser, Boolean isFirst) {
		Integer update = 1;
		if (!isFirst) {
			update = signUserMapper.updateUserSignDay(signUser.getDay(), signUser.getDayPeriod(), signUser.getUserId(), signUser.getUpdateTime());
		}
		Integer points = 0;
		if (update > 0) {
			if (signUser.getDayPeriod() > 1) {
				//发放积分
				SignConfig signConfig = signConfigMapper.selectOne(Wrappers.lambdaQuery(SignConfig.class)
						.like(SignConfig::getType, signUser.getDayPeriod()).last("limit 1"));
				if (signConfig != null) {
					points = ThreadLocalRandom.current().nextInt(signConfig.getMinPoints(), signConfig.getMaxPoints() + 1);
				} else {
					points = signConfigMapper.selectOne(Wrappers.lambdaQuery(SignConfig.class)
							.orderByAsc(SignConfig::getId).last("limit 1")).getMaxPoints();
				}
			} else {
				points = signConfigMapper.selectOne(Wrappers.lambdaQuery(SignConfig.class)
						.orderByAsc(SignConfig::getId).last("limit 1")).getMaxPoints();
			}
			userGalaxyCoinService.sendGalaxyCoinRecord(signUser.getUserId(), points, PointsRecordConst.SIGN, false);
		}
		signUser.setPoints(points);
	}

	/**
	 * 随机概率奖励
	 * 获取下标
	 */
	public Integer randomProbabilityIndex(List<LuckyDrawView> list) {
		int random = -1;
		//总权重
		BigDecimal sums = list.stream().map(LuckyDrawView::getProbability).reduce(BigDecimal::add).get();
		Double totalProbability = sums.doubleValue();
		//产生随机数
		Double randomNumber = ThreadLocalRandom.current().nextDouble();
		//根据随机数在所有奖品分布的区域并确定所抽奖品
		Double d1 = 0d;
		Double d2 = 0d;
		for (int i = 0; i < list.size(); i++) {
			d2 += Double.parseDouble(String.valueOf(list.get(i).getProbability())) / totalProbability;
			if (i == 0) {
				d1 = 0d;
			} else {
				d1 += Double.parseDouble(String.valueOf(list.get(i - 1).getProbability())) / totalProbability;
			}
			if (randomNumber >= d1 && randomNumber < d2) {
				random = i;
				break;
			}
		}
		return random;
	}

	public LuckyDrawView randomNum(LuckyDrawView luckyDrawView, List<LuckyDrawView> list, Integer num, Long userId) {
		if (luckyDrawView.getNum() == 0) {
			return null;
		}
		if (luckyDrawView.getType() == LuckyDraw.Type.coupon) {
			CouponUser couponUser = couponUserMapper.selectOne(Wrappers.lambdaQuery(CouponUser.class)
					.eq(CouponUser::getCouponId, luckyDrawView.getCouponId())
					.eq(CouponUser::getUserId, userId).last("limit 1"));
			if (couponUser != null) {
				Integer index = randomProbabilityIndex(list);
				if (index == -1) {
					throw BusinessRuntimeException.getInstance("系统异常,请刷新页面重新操作");
				}
				LuckyDrawView next = list.get(index);
				num++;
				if (num >= 3) {
					return null;
				}
				return randomNum(next, list, num, userId);
			}
		}
		DateTime zero = DateUtil.beginOfDay(DateTime.now());
		String key = RedisService.key.LOTTERY_KEY.getNameFormat(String.format("%s_%s", zero.toString(), luckyDrawView.getId().toString()));
		Object o = redisService.get(key);
		if (o != null) {
			Integer incr = (Integer) o;
			if (luckyDrawView.getNum() - incr > 0) {
				redisService.incr(key, 1l);
			} else {
				if (num >= 3) {
					return null;
				}
				Integer index = randomProbabilityIndex(list);
				if (index == -1) {
					throw BusinessRuntimeException.getInstance("系统异常,请刷新页面重新操作");
				}
				if (index > list.size()) {
					throw BusinessRuntimeException.getInstance("抽奖异常,请联系客服");
				}
				LuckyDrawView next = list.get(index);
				num++;
				return randomNum(next, list, num, userId);
			}
		} else {
			redisService.set(key, 0, RedisService.key.LOTTERY_KEY.getTimeout());
			redisService.incr(key, 1l);
			return luckyDrawView;
		}
		return luckyDrawView;
	}

	public void checkTaskStatus(TaskFrontView data, Long userId) {
		DateTime now = DateTime.now();
		DateTime beginOfDay = DateUtil.beginOfDay(now);
		DateTime endOfDay = DateUtil.endOfDay(now);
		DateTime beginOfWeek = DateUtil.beginOfWeek(now);
		DateTime endOfWeek = DateUtil.endOfWeek(now);
		LambdaQueryWrapper<TaskUserCompleteRecord> wrapper = Wrappers.lambdaQuery(TaskUserCompleteRecord.class)
				.eq(TaskUserCompleteRecord::getUserId, userId)
				.eq(TaskUserCompleteRecord::getTaskId, data.getId())
				.last("limit 1");
		User user = userMapper.selectById(userId);
		if ("time".equals(data.getTaskLimit())) {
			Boolean isWx = false;
			if ("添加企业微信".equals(data.getTypeName())) {
				isWx = true;
			}
			TaskUserCompleteRecord record = taskUserCompleteRecordMapper.selectOne(wrapper);
			if (record != null) {
				data.setStatus(record.getStatus());
				data.setTaskCompleteRecordId(record.getId());
			}
			if (record == null && isWx && StrUtil.isNotEmpty(user.getUnionid())) {
				CorpUser corpUser = corpUserMapper.selectOne(Wrappers.lambdaQuery(CorpUser.class)
						.ne(CorpUser::getUnionid, "")
						.eq(CorpUser::getUnionid, user.getUnionid())
						.last("limit 1"));
				if (corpUser != null) {
					data.setStatus(TaskUserCompleteRecord.Status.complete);
					if (redisService.setNx(RedisService.key.TASK_TIME_LIMIT_KEY.getNameFormat(String.format("wx_%s", userId)), userId, RedisService.key.TASK_TIME_LIMIT_KEY.getTimeout())) {
						record = new TaskUserCompleteRecord();
						record.setUserId(userId);
						record.setTaskId(data.getId());
						record.setPoints(data.getPoints());
						record.setStatus(TaskUserCompleteRecord.Status.complete);
						taskUserCompleteRecordMapper.insert(record);
					}
				}
			}
		} else if ("day".equals(data.getTaskLimit())) {
			wrapper.between(TaskUserCompleteRecord::getCreatedTime, beginOfDay, endOfDay);
			TaskUserCompleteRecord record = taskUserCompleteRecordMapper.selectOne(wrapper);
			if (record != null) {
				data.setTaskCompleteRecordId(record.getId());
				data.setStatus(record.getStatus());
			}
			handleSpecialTask(userId, data, record, beginOfDay, endOfDay);

		} else if ("week".equals(data.getTaskLimit())) {
			wrapper.between(TaskUserCompleteRecord::getCreatedTime, beginOfWeek, endOfWeek);
			TaskUserCompleteRecord record = taskUserCompleteRecordMapper.selectOne(wrapper);
			if (record != null) {
				data.setTaskCompleteRecordId(record.getId());
				data.setStatus(record.getStatus());
			}
			handleSpecialTask(userId, data, record, beginOfWeek, endOfWeek);
		}
	}

	public void handleSpecialTask(Long userId, TaskFrontView data, TaskUserCompleteRecord record, DateTime beginTime, DateTime endTime) {
		if (TaskTypeEnum.share.getDesc().equals(data.getTypeName())) {
			//邀请人数是否达标
			Integer count = userDistributeSharedMapper.selectCount(Wrappers.lambdaQuery(UserDistributeShared.class)
					.eq(UserDistributeShared::getSharedId, userId)
					.between(UserDistributeShared::getCreatedTime, beginTime, endTime));
			data.setHadInvitedNum(count);
			if (count >= data.getInviteNum() && data.getStatus() == TaskUserCompleteRecord.Status.waiting) {
				data.setStatus(TaskUserCompleteRecord.Status.complete);
				if (record == null) {
					if (redisService.setNx(RedisService.key.TASK_TIME_LIMIT_KEY.getNameFormat(String.format("day_week_%s", userId)), userId, RedisService.key.TASK_TIME_LIMIT_KEY.getTimeout())) {
						record = new TaskUserCompleteRecord();
						record.setUserId(userId);
						record.setTaskId(data.getId());
						record.setPoints(data.getPoints());
						record.setStatus(TaskUserCompleteRecord.Status.complete);
						taskUserCompleteRecordMapper.insert(record);
					}
				}
			}
		} else if (TaskTypeEnum.bind_phone.getDesc().equals(data.getTypeName())) {
			UserBindDetail bindPhone = UserBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
					.eq(UserBindDetail::getUserId, userId).last("limit 1"));
			if (bindPhone != null) {
				data.setPhone(bindPhone.getPhone());
			}
		}
	}

	public void luckyDrawNormalCheck(Long userId) {
		SysConfig lottery_points_limit = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.LOTTERY_POINTS_LIMIT).last("limit 1"));
		User user = userMapper.selectById(userId);
		BigDecimal subGalaxyCoin = BigDecimal.valueOf(Long.parseLong(lottery_points_limit.getSysValue()));
		if (user.getGalaxyCoin().compareTo(subGalaxyCoin) < 0) {
			throw BusinessRuntimeException.getInstance("银河币不足");
		}
		//扣减积分
		Integer sub = userMapper.subUserGalaxyCoin(userId, subGalaxyCoin, user.getGalaxyCoin());
		if (sub != 1) {
			throw BusinessRuntimeException.getInstance("银河币不足");
		}
		userGalaxyCoinService.sendGalaxyCoinRecord(userId, -subGalaxyCoin.intValue(), PointsRecordConst.POINTS_LOTTERY, true);
	}

	public List<Long> luckyDrawSpecificCheck(Long userId) throws Exception {
		SysConfig lottery_specific_goods = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.LOTTERY_SPECIFIC_GOODS).last("limit 1"));
		if (lottery_specific_goods == null) {
			throw BusinessRuntimeException.getInstance("暂未配置特定奖池平台,请联系客服");
		}
		String sysValue = lottery_specific_goods.getSysValue();
		if (StrUtil.isEmpty(sysValue)) {
			throw BusinessRuntimeException.getInstance("");
		}
		List<Long> goodsIdList = Jsons.parseList(sysValue, Long.class);
		Integer num = getSpecificChanceNum(userId);
		if (num <= 0) {
			throw BusinessRuntimeException.getInstance("您的抽奖次数为0");
		}
		Integer update = luckyDrawSpecificChanceMapper.subChanceNum(userId, num);
		if (update != 1) {
			throw BusinessRuntimeException.getInstance("操作频繁,请稍后再试");
		}
		return goodsIdList;
	}

	@Override
	public Integer getSpecificChanceNum(Long userId) {
		//是否有特定奖池抽奖机会
		LuckyDrawSpecificChance chance = luckyDrawSpecificChanceMapper.selectOne(Wrappers.lambdaQuery(LuckyDrawSpecificChance.class)
				.eq(LuckyDrawSpecificChance::getUserId, userId).last("limit 1").select(LuckyDrawSpecificChance::getNum));
		Integer num = 0;
		if (chance == null) {
			return num;
		}
		num = chance.getNum();
		return num;
	}


	@Override
	public List<GroupsRelationView> getSpecificTickets(Long userId) throws Exception {
		SysConfig lottery_specific_goods = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.LOTTERY_SPECIFIC_GOODS).last("limit 1"));
		if (lottery_specific_goods == null) {
			return new ArrayList<>();
		}
		String sysValue = lottery_specific_goods.getSysValue();
		if (StrUtil.isEmpty(sysValue)) {
			return new ArrayList<>();
		}
		List<Long> goodsIdList = Jsons.parseList(sysValue, Long.class);
		MapBuilder builder = MapUtils.builder()
				.field(GroupsRelationView::getUserId, userId)
				.field(GroupsRelationView::getGoodsType, 1)
				.field(GroupsRelationView::getGoodsSecondType, 2)
				.field(GroupsRelationView::getStatus, GroupsRelation.Status.validity.name())
				.field(GroupsRelationView::getExpiryTime).op(Operator.NotNull);
		if (goodsIdList != null && goodsIdList.size() > 0) {
			builder.field(GroupsRelationView::getGoodsId, goodsIdList).op(Operator.InList);
		}
		List<GroupsRelationView> relations = beanSearcher.searchAll(GroupsRelationView.class, builder.build());
		return relations;
	}

	public Long receiveRealGoodsReward(Long userId, LuckyDrawRecord record, Long addressId) {
		if (addressId == null) {
			throw new BusinessRuntimeException("请添加收货地址.");
		}
		User user = userMapper.selectById(userId);
		/* 生成订单 */
		String donNo = SEQUENCE.nextId().toString();
		OrderDon orderDon = new OrderDon();
		orderDon.setOrderNo(donNo);
		orderDon.setOpenId(user.getOpenId());
		BigDecimal zero = BigDecimal.ZERO;
		orderDon.setMoney(zero);
		orderDon.setRealMoney(zero);
		orderDon.setSkuId(record.getSkuId());
		orderDon.setRelationId(0L);
		orderDon.setNum(1);
		orderDon.setGoodsId(record.getGoodsId());
		orderDon.setStatus(record.getType() == LuckyDraw.Type.realGoods ? OrderDon.Status.hasPayment : OrderDon.Status.complete);
		orderDon.setUserId(user.getId());
		orderDon.setType(OrderDon.Type.LOTTERY);
		orderDonMapper.insert(orderDon);

		Address address = addressMapper.selectById(addressId);
		if (address == null) {
			throw new BusinessRuntimeException("请添加收货地址.");
		}
		OrderDonTransport transport = new OrderDonTransport();
		transport.setOrderId(orderDon.getId());
		transport.setReceiver(address.getReceiver());
		transport.setPhone(address.getPhone());
		transport.setProvince(address.getProvince());
		transport.setCity(address.getCity());
		transport.setDistrict(address.getDistrict());
		transport.setAddress(address.getAddress());
		orderDonTransportMapper.insert(transport);

		return orderDon.getId();
	}

	public void updateRelationExpiryTime(Long userId, Long relationId, Integer days) {
		//增加续费时长
		GroupsRelation relation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
				.eq(GroupsRelation::getUserId, userId)
				.eq(GroupsRelation::getId, relationId)
				.eq(GroupsRelation::getStatus, GroupsRelation.Status.validity)
				.last("limit 1"));
		if (relation == null) {
			throw BusinessRuntimeException.getInstance("该车票不存在");
		}
		if (relation.getExpiryTime() == null) {
			throw BusinessRuntimeException.getInstance("该车位未发车,请在发车后延长车票时长");
		}
		Date expiryTime = relation.getExpiryTime();
		relation.setExpiryTime(DateUtil.offsetDay(expiryTime, days));
		groupsRelationMapper.updateById(relation);
	}

	@Override
	public void addSpecificChanceNum(Long userId, Long orderId, Long goodsId, Long skuId) throws Exception {
		if (!checkSpecificGoods(goodsId)) {
			return;
		}
		//加入企微之后 发放抽奖机会
		if (groupRelationFrontService.isJoinCorpWx(userId, false, true)) {
			addSpecificChanceNumNoWxCorp(userId, orderId, goodsId, skuId);
		}
	}

	@Override
	public void addSpecificChanceNumNoWxCorp(Long userId, Long orderId, Long goodsId, Long skuId) {
		if (saveChanceRecord(userId, orderId, goodsId, skuId)) {
			LuckyDrawSpecificChance chance = luckyDrawSpecificChanceMapper.selectOne(Wrappers.lambdaQuery(LuckyDrawSpecificChance.class)
					.eq(LuckyDrawSpecificChance::getUserId, userId).last("limit 1").select(LuckyDrawSpecificChance::getNum));
			if (chance == null) {
				try {
					LuckyDrawSpecificChance entity = new LuckyDrawSpecificChance();
					entity.setUserId(userId);
					entity.setNum(1);
					luckyDrawSpecificChanceMapper.insert(entity);
				} catch (DuplicateKeyException e) {
					luckyDrawSpecificChanceMapper.addChanceNum(userId);
				}
			} else {
				luckyDrawSpecificChanceMapper.addChanceNum(userId);
			}
		}
	}

	@Override
	public void subSpecificChanceNum(Long userId, Long orderId, Long goodsId, Date refundTime) throws Exception {
		if (!checkSpecificGoods(goodsId)) {
			return;
		}
		LuckyDrawSpecificChance chance = luckyDrawSpecificChanceMapper.selectOne(Wrappers.lambdaQuery(LuckyDrawSpecificChance.class)
				.eq(LuckyDrawSpecificChance::getUserId, userId).last("limit 1").select(LuckyDrawSpecificChance::getNum));
		if (chance == null) {
			return;
		}
		LuckyDrawSpecificChanceRecord record = luckyDrawSpecificChanceRecordMapper.selectOne(Wrappers.lambdaQuery(LuckyDrawSpecificChanceRecord.class)
				.eq(LuckyDrawSpecificChanceRecord::getOrderId, orderId)
				.eq(LuckyDrawSpecificChanceRecord::getUserId, userId)
				.last("limit 1"));
		if (record == null) {
			return;
		}
		record.setRefundTime(refundTime);
		luckyDrawSpecificChanceRecordMapper.updateById(record);
		luckyDrawSpecificChanceMapper.subChanceNumNoRepeat(userId);
	}

	public Boolean checkSpecificGoods(Long goodsId) throws Exception {
		SysConfig lottery_specific_goods = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.LOTTERY_SPECIFIC_GOODS).last("limit 1"));
		if (lottery_specific_goods == null) {
			return false;
		}
		String sysValue = lottery_specific_goods.getSysValue();
		if (StrUtil.isEmpty(sysValue)) {
			return false;
		}
		List<Long> goodsIdList = Jsons.parseList(sysValue, Long.class);

		if (goodsIdList.isEmpty() || goodsIdList.contains(null)) {
			return false;
		}
		if (goodsIdList.contains(goodsId)) {
			return true;
		}
		return false;
	}

	public Boolean saveChanceRecord(Long userId, Long orderId, Long goodsId, Long skuId) {
		try {
			LuckyDrawSpecificChanceRecord en = luckyDrawSpecificChanceRecordMapper.selectOne(Wrappers.lambdaQuery(LuckyDrawSpecificChanceRecord.class)
					.eq(LuckyDrawSpecificChanceRecord::getOrderId, orderId).last("limit 1"));
			if (en == null) {
				LuckyDrawSpecificChanceRecord record = new LuckyDrawSpecificChanceRecord();
				record.setUserId(userId);
				record.setOrderId(orderId);
				record.setGoodsId(goodsId);
				record.setSkuId(skuId);
				luckyDrawSpecificChanceRecordMapper.insert(record);
				return true;
			}
			return false;
		} catch (DuplicateKeyException e) {
			return false;
		}
	}
}
