package com.tzy.listener.mq;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.alipay.api.domain.BrandInfos;
import com.google.common.collect.Lists;
import com.rabbitmq.client.Channel;
import com.tzy.app.domain.act.CodeRecordDTO;
import com.tzy.app.dto.TypeCountDTO;
import com.tzy.app.dto.group.GoodsActRecordDTO;
import com.tzy.app.mapper.AppCarouselPictureMapper;
import com.tzy.app.mapper.GoodsActRecordMapper;
import com.tzy.brand.member.domain.MemberUserRelation;
import com.tzy.brand.member.dto.BrandMemberInfoDTO;
import com.tzy.brand.member.mapper.MemberUserRelationMapper;
import com.tzy.common.constant.Constants;
import com.tzy.common.constant.MqConstans;
import com.tzy.common.core.domain.entity.SysDictData;
import com.tzy.common.dto.GoodsQuery;
import com.tzy.common.dto.PayActDTO;
import com.tzy.common.dto.act.ActExchangeConfig;
import com.tzy.common.dto.act.GroupSaleCodeDTO;
import com.tzy.common.dto.group.GroupActRecord;
import com.tzy.common.exception.ServiceException;
import com.tzy.common.utils.DateUtils;
import com.tzy.common.utils.StringUtils;
import com.tzy.common.utils.bean.JSONTools;
import com.tzy.framework.util.RedisUtils;
import com.tzy.sportcard.api.bean.act.AppActManage;
import com.tzy.sportcard.api.bean.act.GoodsActRecord;
import com.tzy.sportcard.api.bean.act.UserListActParam;
import com.tzy.sportcard.api.domain.GoodsInfo;
import com.tzy.sportcard.api.domain.GoodsSerialDto;
import com.tzy.sportcard.api.mapper.AppActManageMapper;
import com.tzy.sportcard.api.service.AsyncAppService;
import com.tzy.sportcard.api.service.GroupApiService;
import com.tzy.sportcard.api.service.MineApiService;
import com.tzy.sportcard.base.service.CommonCacheService;
import com.tzy.sportcard.group.domain.CardGroupGoods;
import com.tzy.sportcard.group.domain.CardGroupInfo;
import com.tzy.sportcard.group.domain.CardGroupOrderInfo;
import com.tzy.sportcard.group.domain.TzyMerchantInfo;
import com.tzy.sportcard.group.service.*;
import com.tzy.sportcard.group.service.impl.AppActServiceImpl;
import com.tzy.sportcard.group.service.impl.GroupActService;
import com.tzy.sportcard.point.domain.AppUserPointRecord;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.common.Strings;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;


@Slf4j
@Component
public class GroupFullConsumer {

	@Autowired
	private MineApiService mineApiService;
	@Autowired
	private ICardGroupOrderInfoService cardGroupOrderInfoService;
	@Autowired
	private ICardGroupInfoService cardGroupInfoService;
	@Autowired
	private ITzyMerchantInfoService merchantInfoService;
	@Resource
	private AppCarouselPictureMapper appCarouselPictureMapper;
	@Autowired
	private AsyncAppService asyncAppService;
	@Resource
	private ICardGroupGoodsService cardGroupGoodsService;
	@Resource
	private AppActService appActService;
	@Resource
	private RedisUtils redisUtils;
	@Resource
	private CommonCacheService commonCacheService;
	@Resource
	private GroupApiService groupApiService;
	@Resource
	private RabbitTemplate rabbitTemplate;
	@Resource
	private GoodsActRecordMapper goodsActRecordMapper;
	@Resource
	private GroupActService groupActService;
	@Resource
	private MemberUserRelationMapper memberUserRelationMapper;

	@RabbitHandler
	@RabbitListener(queuesToDeclare = @Queue(MqConstans.QUEUE_GROUP_FULL))
	public void groupFullConsumer(Long groupInfoId, Channel channel, Message message) throws IOException {
		log.info("拼团组齐消费开始,id:{}", groupInfoId);
		try {
			groupFullById(groupInfoId);
		} catch (Exception e) {
			log.info("拼团组齐消费异常,参数:{}", groupInfoId, e);
		}
		channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
	}

	private void groupFullById(Long groupInfoId) {
		CardGroupInfo cardGroupInfo = cardGroupInfoService.selectCardGroupInfoById(groupInfoId);
		if (cardGroupInfo == null) {
			return;
		}
		//预售
		boolean isPreSale = cardGroupInfo.isPreSale();
		CardGroupOrderInfo condition = new CardGroupOrderInfo();
		condition.setGroupInfoId(groupInfoId);
		if (isPreSale) {
			cardGroupOrderInfoService.expireUnPayOrder(groupInfoId);
		} else {
			condition.setStatus(100L);
			checkHasUnPayOrder(groupInfoId, condition);
		}
		asyncAppService.noticeGroupFull(cardGroupInfo);
		condition.setStatus(null);
		condition.setColumnsearch(" and cgoi.status in (101,102,103,104,105,106,301,302) AND  cgoi.order_sub_type is null ");
		List<CardGroupOrderInfo> orders = cardGroupOrderInfoService.selectCardGroupOrderInfoList(condition);
		if (orders.isEmpty()) {
			return;
		}
		boolean isMerActInfo = StringUtils.isNotEmpty(cardGroupInfo.getPointType()) && cardGroupInfo.getPointType().startsWith(Constants.POINT_TYPE_MERCHANT_ACT_PRE);
		if (isMerActInfo) {
			//修改关联商城拼豆订单为待发货
			int i = cardGroupOrderInfoService.changeMallOrderToShipment(cardGroupInfo.getId());
			log.info("拼团组齐,关联拼豆订单待发货变更,组团id:{},个数:{}", cardGroupInfo.getId(), i);
		}
		//------------------拼豆模式后已弃--------------
		//精美卡片
		if (!isMerActInfo && Constants.ONE.equals(cardGroupInfo.getNonEmpty()) && cardGroupInfo.getGiftCardId() != null) {
			sendUserGiftCard(groupInfoId);
		}
		//------------------拼豆模式后已弃--------------
		//积分
		//addUserPointByGroupOrdersV2(cardGroupInfo, isPreSale, orders);
		addUserPointByGroupOrdersV3(cardGroupInfo, isPreSale, orders);
		//支付活动
		buildOrderPayAct(groupInfoId, orders);
		//商家活动
		buildMerchantAct(cardGroupInfo);
		//卡密收集
		buildListAct(cardGroupInfo);
		editGroupInfo(cardGroupInfo);
		//预售退款
		autoRefund(groupInfoId, isPreSale, orders);
		log.info("拼团组齐消费结束,id:{},活动积分类型:{}", groupInfoId, cardGroupInfo.getActPointType());
	}

	private void sendUserGiftCard(Long groupInfoId) {
		GroupActRecord actRecord = new GroupActRecord().setType(Constants.GROUP_GIFT_CARD).setRefId(groupInfoId.intValue()).setActType(Constants.GROUP_GIFT_CARD);
		rabbitTemplate.convertAndSend(MqConstans.QUEUE_GROUP_GIFT_CARD, JSON.toJSONString(actRecord));
	}

	private void buildListAct(CardGroupInfo cardGroupInfo) {
		if(cardGroupInfo.getPaniniListId()==null){
			return;
		}
		//panini list活动
		List<GoodsActRecord> userListAct = groupApiService.getUserListAct(cardGroupInfo.getPaniniListId());
		if (CollectionUtils.isEmpty(userListAct)) {
			return;
		}
		GoodsActRecord act = userListAct.get(0);
		String actType = act.getActType();
		if (Constants.LIST_ACT_SELECT_NUM.equals(actType)) {
			ActExchangeConfig actConfig = act.getActConfig();
			if (actConfig != null && StringUtils.isNotEmpty(actConfig.getExchangeActType())) {
				List<TypeCountDTO> countList = cardGroupGoodsService.getUserGoodsNum(cardGroupInfo.getId());
				countList.forEach(c -> {
					AppUserPointRecord pointRecord = new AppUserPointRecord();
					pointRecord.setType(actConfig.getExchangeActType());
					pointRecord.setChangePoint(c.getNum().longValue());
					pointRecord.setUserId(Long.parseLong(c.getType()));
					pointRecord.setOrderId(cardGroupInfo.getId());
					pointRecord.setOrderNo(cardGroupInfo.getCode());
					pointRecord.setCreateTime(new Date());
					pointRecord.setPointRate(1d);
					mineApiService.addUserPoint(pointRecord);
				});
			}
		} else {
			boolean isInAct = checkListActByInfoType(actType, cardGroupInfo.getType());
			if (!isInAct) {
				return;
			}
			UserListActParam listActParam = new UserListActParam(cardGroupInfo.getId(), cardGroupInfo.getGoodsType(), cardGroupInfo.getPaniniListId(), actType);
			rabbitTemplate.convertAndSend(MqConstans.EXCHANGE_USER_LIST_ACT, MqConstans.ROUTING_KEY_USER_LIST_ACT, JSON.toJSONString(listActParam));
		}
	}

	private boolean checkListActByInfoType(String actType, String infoType) {
		if (Constants.INFO_TYPE_BUY_TEAM.equals(infoType)) {
			return false;
		}
		if (actType.endsWith(Constants.ACT_GOODS_TYPE_SET) && !Constants.INFO_TYPE_SETS.equals(infoType)) {
			return false;
		}
		if (actType.endsWith(Constants.ACT_GOODS_TYPE_PLAYER) && Constants.INFO_TYPE_TEAM.equals(infoType)) {
			return false;
		}
		if (actType.endsWith(Constants.ACT_GOODS_TYPE_TEAM) && Constants.INFO_TYPE_PLAYER.equals(infoType)) {
			return false;
		}
		return true;
	}

	private void checkHasUnPayOrder(Long groupInfoId, CardGroupOrderInfo condition) {
		int i = 0;
		while (true) {
			List<CardGroupOrderInfo> upPayOrders = cardGroupOrderInfoService.selectCardGroupOrderInfoList(condition);
			if (upPayOrders.isEmpty() || i > 10) {
				break;
			}
			i++;
			log.info("存在未支付订单:{},次数:{}", groupInfoId, i);
			try {
				Thread.sleep(1000L);
			} catch (InterruptedException e) {
			}
		}
	}

	private void addUserPointByGroupOrdersV2(CardGroupInfo cardGroupInfo, boolean isPreSale, List<CardGroupOrderInfo> orders) {
		boolean isPointCat = StringUtils.isNotEmpty(cardGroupInfo.getPointType()) &&
				cardGroupInfo.getPointType().startsWith(Constants.POINT_TYPE_MERCHANT_ACT_PRE);
		int commonRate = isPointCat ? 1 : 100;
		boolean isGroupRateAct = StringUtils.isNotEmpty(cardGroupInfo.getActType())
				&& cardGroupInfo.getActType().startsWith(Constants.GROUP_ACT_RATE_PRE);
		int actRate = isGroupRateAct ? cardGroupInfo.getPointRate() : commonRate;
		List<AppUserPointRecord> pointRecords = orders.stream()
				.flatMap(order -> Stream.of(
						buildUserPointRecord(order, Constants.POINT_TYPE_COMMON, isPreSale, commonRate, isPointCat),
						buildUserPointRecord(order, Constants.POINT_TYPE_USER_GROWTH, isPreSale, commonRate, isPointCat),
						StringUtils.isNotEmpty(cardGroupInfo.getActPointType()) && groupApiService.checkOrderAct(cardGroupInfo.getActType(), order.getPaymentSuccessTime()) ?
								buildUserPointRecord(order, cardGroupInfo.getActPointType(), isPreSale, actRate, isPointCat) : null
				))
				.filter(Objects::nonNull)
				.collect(Collectors.toList());
		int i = 0;
		boolean isSuccess = false;
		while (i < 3) {
			i++;
			try {
				mineApiService.batchAddPointRecords(pointRecords);
				isSuccess = true;
				break;
			} catch (Exception e) {
				log.warn("拼团组齐积分记录异常,code:{},msg:", cardGroupInfo.getCode(), e);
			}
			try {
				Thread.sleep(100L * i + 50);
			} catch (InterruptedException ignored) {}
		}
		if (!isSuccess) {
			throw new ServiceException("拼团组齐积分记录异常");
		}
	}

	private void addUserPointByGroupOrdersV3(CardGroupInfo cardGroupInfo, boolean isPreSale, List<CardGroupOrderInfo> orders) {
		boolean isPointCat = StringUtils.isNotEmpty(cardGroupInfo.getPointType()) &&
				cardGroupInfo.getPointType().startsWith(Constants.POINT_TYPE_MERCHANT_ACT_PRE);
		int commonRate = isPointCat ? 1 : 100;
		boolean isGroupRateAct = StringUtils.isNotEmpty(cardGroupInfo.getActType())
				&& cardGroupInfo.getActType().startsWith(Constants.GROUP_ACT_RATE_PRE);
		int actRate = isGroupRateAct ? cardGroupInfo.getPointRate() : commonRate;
		List<AppUserPointRecord> pointRecords = Lists.newArrayList();
		// 送积分
		boolean hashSaleCode = hasGroupSaleCode(cardGroupInfo);	//判断是否生态购
		// 根据paniniListId 查询关联的活动（goods_act_record）
		List<GoodsActRecord> goodsActRecordList = goodsActRecordMapper.selectListByGoodsId(cardGroupInfo.getPaniniListId());
		Set<Long> filterUserId = new HashSet<>();
		for(CardGroupOrderInfo order : orders){
			// 平台通用积分
			AppUserPointRecord commonRecord = buildUserPointRecord(order, Constants.POINT_TYPE_COMMON, isPreSale, commonRate, isPointCat);
			pointRecords.add(commonRecord);
			// 平台成长值
			AppUserPointRecord userGrowthRecord = buildUserPointRecord(order, Constants.POINT_TYPE_USER_GROWTH, isPreSale, commonRate, isPointCat);
			pointRecords.add(userGrowthRecord);
			// 查询用户是否加入品牌会员
			BrandMemberInfoDTO brandInfo = memberUserRelationMapper.getBrandInfo(order.getMerchantId());
			if(brandInfo != null) {
				MemberUserRelation memberUserRelation = memberUserRelationMapper.checkMemberUserRelation(order.getUserId().intValue(), brandInfo.getMerchantGroupId().intValue());
				if (memberUserRelation != null) {
					int status = memberUserRelation.getStatus();
					// 必须是正常会员或者注销之前的订单
					if (1 == status || (0 == status && order.getPaymentSuccessTime().before(memberUserRelation.getLogoutTime()))) {
						com.alibaba.fastjson2.JSONObject commonConfig = JSONTools.parseObject(memberUserRelation.getCommonConfig()); // 品牌积分成长值配置
						// 品牌会员积分
						AppUserPointRecord brandMemberPointRecord = buildUserPointRecord3(order, Constants.BRAND_POINT_TYPE_PRE + memberUserRelation.getMerchantGroupId(),
								isPreSale, commonRate, isPointCat, commonConfig.getInteger("pointRate"));
						if (brandMemberPointRecord != null) {
							brandMemberPointRecord.setMerchantGroupId(memberUserRelation.getMerchantGroupId());
							brandMemberPointRecord.setMerchantId(order.getMerchantId());
							brandMemberPointRecord.setPointRate(commonConfig.getDouble("pointRate"));
							pointRecords.add(brandMemberPointRecord);
						}
						// 品牌会员成长值
						AppUserPointRecord brandUserGrowthRecord = buildUserPointRecord3(order, Constants.BRAND_GROWTH_TYPE_PRE + memberUserRelation.getMerchantGroupId(),
								isPreSale, 10, isPointCat, commonConfig.getInteger("growthRate"));
						if (brandUserGrowthRecord != null) {
							brandUserGrowthRecord.setMerchantGroupId(memberUserRelation.getMerchantGroupId());
							brandUserGrowthRecord.setMerchantId(order.getMerchantId());
							brandUserGrowthRecord.setPointRate(commonConfig.getDouble("growthRate"));
							pointRecords.add(brandUserGrowthRecord);
						}
					}
				}
			}

			AppUserPointRecord luckyPointRecord2025 = buildLuckyPoint2025(order, "", isPreSale, commonRate, isPointCat);
			if(luckyPointRecord2025 != null) {
				pointRecords.add(luckyPointRecord2025);
			}
			if(StringUtils.isNotEmpty(cardGroupInfo.getActPointType()) && groupApiService.checkOrderAct(cardGroupInfo.getActType(), order.getPaymentSuccessTime())){
				AppUserPointRecord actPointRecord = buildUserPointRecord(order, cardGroupInfo.getActPointType(), isPreSale, actRate, isPointCat);
				pointRecords.add(actPointRecord);
			}
			/*if(groupApiService.checkOrderActV2(cardGroupInfo.getActType(), order.getPaymentSuccessTime())){
				AppUserPointRecord actPointRecord = buildUserPointRecord(order, cardGroupInfo.getActPointType(), isPreSale, actRate, isPointCat);
				pointRecords.add(actPointRecord);
			}*/
			// 拼团成功奖励
			List<AppUserPointRecord> groupFullRecords = buildUserPointRecord2(order, hashSaleCode, goodsActRecordList, filterUserId, isPointCat);
			if(!CollectionUtils.isEmpty(groupFullRecords)) {
				pointRecords.addAll(groupFullRecords);
			}
		}
		pointRecords.removeIf(Objects::isNull); // 过滤null元素

		int i = 0;
		boolean isSuccess = false;
		while (i < 3) {
			i++;
			try {
				mineApiService.batchAddPointRecords(pointRecords);
				isSuccess = true;
				break;
			} catch (Exception e) {
				log.warn("拼团组齐积分记录异常,code:{},msg:", cardGroupInfo.getCode(), e);
			}
			try {
				Thread.sleep(100L * i + 50);
			} catch (InterruptedException ignored) {}
		}
		if (!isSuccess) {
			throw new ServiceException("拼团组齐积分记录异常");
		}
	}

	/**
	 * 2025-618沙滩球活动
	 */
	private AppUserPointRecord buildLuckyPoint2025(CardGroupOrderInfo orderInfos, String type, boolean isPreSale, Integer commonRate, boolean isPointCat){
		List<SysDictData> sysDictDatas = commonCacheService.getCommonDictData("app_hot_type_times_cache",
				"hb_act_lucky_2025_618","1", null, -1);
		if(!CollectionUtils.isEmpty(sysDictDatas)) {
			com.alibaba.fastjson2.JSONObject jsonObject = JSONTools.parseObject(sysDictDatas.get(0).getDictValue());
			Date startTime = jsonObject.getDate("startTime");
			Date endTime = jsonObject.getDate("endTime");
			if (orderInfos.getPaymentSuccessTime().after(startTime) && orderInfos.getPaymentSuccessTime().before(endTime)) {
				BigDecimal refundFree = orderInfos.getRefundFee() != null ? orderInfos.getRefundFee() : BigDecimal.ZERO;
				BigDecimal amount;
				if (isPreSale) {
					amount = orderInfos.getSettlementAmount();
				} else {
					amount = isPointCat ? new BigDecimal(String.valueOf(orderInfos.getPoint())) : orderInfos.getActualPayment().subtract(refundFree);
				}
				if (amount.doubleValue() <= 0) {
					return null;
				}
				BigDecimal pointRate = new BigDecimal(commonRate.toString());
				Long points = amount.multiply(pointRate).longValue();

				AppUserPointRecord pointRecord = new AppUserPointRecord();
				pointRecord.setType(jsonObject.getString("pointType"));
				pointRecord.setChangePoint(points);
				pointRecord.setUserId(orderInfos.getUserId());
				pointRecord.setOrderId(orderInfos.getId());
				pointRecord.setOrderNo(orderInfos.getOrderNo());
				pointRecord.setCreateTime(new Date());
				pointRecord.setPointRate(commonRate.doubleValue());
				pointRecord.setTotalSale(amount);
				return pointRecord;
			}
		}
		return null;
	}
	private void buildOrderPayAct(Long groupInfoId, List<CardGroupOrderInfo> orders) {
		List<SysDictData> payActs = asyncAppService.getPayActs(PayActDTO.TYPE_PAY_AMOUNT_TURNTABLE);
		if (payActs != null && !payActs.isEmpty()) {
			Map<Long, CardGroupOrderInfo> distinctUserOrders = orders.stream().collect(Collectors.toMap(CardGroupOrderInfo::getUserId, o -> o, (key1, key2) -> key1));
			distinctUserOrders.values().forEach(order -> asyncAppService.aftPayAct(order, PayActDTO.TYPE_PAY_AMOUNT_TURNTABLE));
			log.info("记录大转盘活动组团id:{}", groupInfoId);
		}
	}

	private void autoRefund(Long groupInfoId, boolean isPreSale, List<CardGroupOrderInfo> orders) {
		String groupRefundKey = "app_group_auto_refund" + groupInfoId;
		if (isPreSale && !redisUtils.hasKey(groupRefundKey)) {
			List<CardGroupOrderInfo> refundOrders = orders.stream()
					.filter(o -> o.getSettlementAmount().compareTo(BigDecimal.ZERO) == 0 || !Constants.ZERO.equals(o.getMissCardCount()))
					.collect(Collectors.toList());
			asyncAppService.refundPreSaleOrders(refundOrders);
			redisUtils.set(groupRefundKey, 1);
			log.info("预售组团退款记录,id:{}", groupInfoId);
		}
	}

	private void editGroupInfo(CardGroupInfo cardGroupInfo) {
		Long groupInfoId=cardGroupInfo.getId();
		CardGroupInfo info = new CardGroupInfo();
		info.setId(groupInfoId);
		info.setAddPointFlag(Constants.ZERO);
		info.setSortDefault(0);
		cardGroupInfoService.updateCardGroupInfo(info);
		TzyMerchantInfo merchantInfo = new TzyMerchantInfo();
		merchantInfo.setId(cardGroupInfo.getMerchantId().longValue());
		merchantInfo.setSaleNum(cardGroupInfoService.findMerchantSaleNum(cardGroupInfo.getMerchantId().longValue()));
		merchantInfoService.updateTzyMerchantInfo(merchantInfo);
		appCarouselPictureMapper.cancelBanner(Constants.REDIRECT_PATH + groupInfoId);
		redisUtils.del("order_group_cache:"+groupInfoId);
		redisUtils.hdel(Constants.INFO_TEAM_TO_RANDOM_CACHE, groupInfoId.toString());
		redisUtils.set("group_full_flag"+groupInfoId,1,3600);
	}

	private void buildMerchantAct(CardGroupInfo cardGroupInfo) {
		if (StringUtils.isEmpty(cardGroupInfo.getHotTypeConfig())) {
			return;
		}
		List<GoodsActRecordDTO> actConfigs = JSON.parseArray(cardGroupInfo.getHotTypeConfig(), GoodsActRecordDTO.class);
		if (CollectionUtils.isEmpty(actConfigs)) {
			return;
		}
		GoodsActRecordDTO config = actConfigs.get(0);
		if (Constants.GROUP_ACT_TYPE_RANDOM.equals(config.getSubType())) {
			//随机卡密分配活动
			String actType = config.getActType();
			if (!Constants.MERCHANT_ACT_GROUP_FULL.equals(actType)) {
				return;
			}
			List<CardGroupGoods> actGoods = groupApiService.getGroupActGoods(cardGroupInfo.getId());
			if (CollectionUtils.isEmpty(actGoods)) {
				return;
			}
			actGoods.forEach(goods -> appActService.sendPrize(goods.getUserId(), goods.getActId().longValue(), config.getActValueType()));
			editGoodsActFlag(cardGroupInfo);
			Map<Integer, List<CardGroupGoods>> userNotifyData = actGoods.stream().collect(Collectors.groupingBy(CardGroupGoods::getUserId));
			String prizeName = AppActServiceImpl.getPrizeName(config.getActDesc());
			userNotifyData.keySet().forEach(key -> {
				List<CardGroupGoods> goodsList = userNotifyData.get(key);
				CardGroupGoods goods = goodsList.get(0);
				String userPrizeName = prizeName;
				if (goodsList.size() > 1) {
					userPrizeName = prizeName + "等活动奖品";
				}
				appActService.sendMerchantActNotify(cardGroupInfo.getName(), goods.getUserOrderId().longValue(), goods.getUserId(),
						goods.getUserNickname(), userPrizeName, config.getActValueType(), config.getName());
			});
		} else if (Constants.GROUP_ACT_TYPE_SELECT.equals(config.getSubType())) {
			//指定卡密
			Long groupInfoId = cardGroupInfo.getId();
			List<GoodsActRecord> allActGoods = cardGroupGoodsService.getActGoods(groupInfoId, Constants.MERCHANT_ACT_GROUP_FULL);
			if (!allActGoods.isEmpty()) {
				List<Long> goodsIdList = allActGoods.stream().filter(a -> a.getGoodsId() != null).map(GoodsActRecord::getGoodsId).collect(Collectors.toList());
				GoodsQuery query = new GoodsQuery().setGroupInfoId(cardGroupInfo.getId()).setIds(goodsIdList).setActStatus(0);
				List<GoodsSerialDto> actGoods = cardGroupGoodsService.selectGoods(cardGroupInfo.isNewGoodsType(), query);
				actGoods.forEach(goods -> appActService.sendGoodsActPrize(goods, allActGoods, cardGroupInfo.getName()));
				editGoodsActFlag(cardGroupInfo);
				Map<Integer, List<GoodsSerialDto>> userNotifyData = actGoods.stream().collect(Collectors.groupingBy(GoodsSerialDto::getUserId));
				userNotifyData.keySet().forEach(key -> {
					List<GoodsSerialDto> goodsList = userNotifyData.get(key);
					GoodsSerialDto goods = goodsList.get(0);
					List<GoodsActRecord> actRecords = allActGoods.stream().filter(a -> a.getGoodsId() != null && a.getGoodsId().intValue() == goods.getId()).collect(Collectors.toList());
					GoodsActRecord actRecord = actRecords.get(0);
					String prizeName = AppActServiceImpl.getPrizeName(actRecord.getActDesc());
					if (goodsList.size() > 1) {
						prizeName = prizeName + ".等活动奖品";
					}
					appActService.sendMerchantActNotify(cardGroupInfo.getName(), goods.getUserOrderId().longValue(),
							goods.getUserId(), goods.getNickname(), prizeName, config.getActValueType(), config.getName());
				});
			}
		}
	}

	private void editGoodsActFlag(CardGroupInfo cardGroupInfo) {
		GoodsQuery condition = new GoodsQuery().setGroupInfoId(cardGroupInfo.getId());
		CardGroupGoods goods=new CardGroupGoods();
		goods.setActStatus(1);
		cardGroupGoodsService.updateGoodsByCond(goods,condition);
	}


	private void addPoint(CardGroupOrderInfo orderInfos, String type, boolean isPreSale, Integer actPointRate, boolean isPointCat) {
		AppUserPointRecord pointRecord = buildUserPointRecord(orderInfos, type, isPreSale, actPointRate, isPointCat);
		if (pointRecord == null) return;
		//增加积分明细记录
		mineApiService.addUserPoint(pointRecord);
	}

	private AppUserPointRecord buildUserPointRecord(CardGroupOrderInfo orderInfos, String type, boolean isPreSale, Integer actPointRate, boolean isPointCat) {
		BigDecimal refundFree = orderInfos.getRefundFee() != null ? orderInfos.getRefundFee() : BigDecimal.ZERO;
		BigDecimal amount;
		if (isPreSale) {
			amount = orderInfos.getSettlementAmount();
		} else {
			amount = isPointCat ? new BigDecimal(String.valueOf(orderInfos.getPoint())) : orderInfos.getActualPayment().subtract(refundFree);
		}
		if (amount.doubleValue() <= 0) {
			return null;
		}
		BigDecimal pointRate = new BigDecimal(actPointRate.toString());
		Long points = amount.multiply(pointRate).longValue();

		AppUserPointRecord pointRecord = new AppUserPointRecord();
		pointRecord.setType(type);
		pointRecord.setChangePoint(points);
		pointRecord.setUserId(orderInfos.getUserId());
		pointRecord.setOrderId(orderInfos.getId());
		pointRecord.setOrderNo(orderInfos.getOrderNo());
		pointRecord.setCreateTime(new Date());
		pointRecord.setPointRate(pointRate.doubleValue());
		pointRecord.setTotalSale(amount);
		return pointRecord;
	}

	private List<AppUserPointRecord> buildUserPointRecord2(CardGroupOrderInfo orderInfos, boolean hashSaleCode,
														   List<GoodsActRecord> goodsActRecordList, Set<Long> filterUserId, boolean isPointCat){
		List<AppUserPointRecord> results = Lists.newArrayList();
		if(CollectionUtils.isEmpty(goodsActRecordList)) {
			log.debug("拼团组齐次数无活动");
			return results;
		}
		Map<String, List<GoodsActRecord>> groupMap = goodsActRecordList.stream().collect(Collectors.groupingBy(GoodsActRecord::getCategory));
		BigDecimal refundFree = orderInfos.getRefundFee() != null ? orderInfos.getRefundFee() : BigDecimal.ZERO;
		BigDecimal amount = isPointCat ? new BigDecimal(String.valueOf(orderInfos.getPoint())) : orderInfos.getActualPayment().subtract(refundFree);
		groupMap.keySet().forEach(key -> {
			GoodsActRecord actPoint = groupMap.get(key).get(0);
			JSONObject prop1Obj = JSONObject.parseObject(actPoint.getProp1());
			if(Strings.isEmpty(prop1Obj.getString("pointType"))){ // 如果不是送积分的活动 不走后面的逻辑
				return;
			}
			if(Constants.GROUP_ACT_RATE.equals(key)){	// 	倍率积分活动
				List<GoodsActRecord> actPointList = groupMap.get(key);
				actPointList.stream()
						.filter(record -> Objects.equals(JSONObject.parseObject(record.getProp1()).getBooleanValue("needSaleCode"), hashSaleCode))
						.findFirst()
						.ifPresent(filterRecord -> {
							if(!checkActTime(filterRecord, orderInfos.getPaymentSuccessTime())){
								return;
							}
							results.add(createPointRecord(JSONObject.parseObject(filterRecord.getProp1()), amount, orderInfos));
						});
			} else if(Constants.GROUP_FULL_COUNT.equals(key)){
				log.debug("拼团组齐次数group_full_count--------");
				if(!filterUserId.contains(orderInfos.getUserId())) {	//	拼团组齐只送一次
					if(!checkActTime(actPoint, orderInfos.getPaymentSuccessTime())){
						log.debug("拼团组齐次数用户支付时间不在范围内");
						return;
					}

					// 拼团组齐次数
					results.add(createPointRecord(prop1Obj, BigDecimal.ONE, orderInfos));
					filterUserId.add(orderInfos.getUserId());
				}
			} else{
				if(!checkActTime(actPoint, orderInfos.getPaymentSuccessTime())){
					return;
				}
				results.add(createPointRecord(prop1Obj, amount, orderInfos));
			}
		});

		return results;
	}

	private AppUserPointRecord buildUserPointRecord3(CardGroupOrderInfo orderInfos, String type, boolean isPreSale, Integer actPointRate, boolean isPointCat, Integer brandRate) {
		BigDecimal refundFree = orderInfos.getRefundFee() != null ? orderInfos.getRefundFee() : BigDecimal.ZERO;
		BigDecimal amount;
		if (isPreSale) {
			amount = orderInfos.getSettlementAmount();
		} else {
			amount = isPointCat ? new BigDecimal(String.valueOf(orderInfos.getPoint())) : orderInfos.getActualPayment().subtract(refundFree);
		}
		if (amount.doubleValue() <= 0) {
			return null;
		}
		BigDecimal pointRate = new BigDecimal(actPointRate.toString());
		Long points = amount.multiply(pointRate).divide(new BigDecimal(brandRate), 0, RoundingMode.HALF_UP).longValue();

		AppUserPointRecord pointRecord = new AppUserPointRecord();
		pointRecord.setType(type);
		pointRecord.setChangePoint(points);
		pointRecord.setUserId(orderInfos.getUserId());
		pointRecord.setOrderId(orderInfos.getId());
		pointRecord.setOrderNo(orderInfos.getOrderNo());
		pointRecord.setCreateTime(new Date());
		pointRecord.setPointRate(pointRate.doubleValue());
		pointRecord.setTotalSale(amount);
		return pointRecord;
	}

	// 判断订单是否在活动有效期
	private boolean checkActTime(GoodsActRecord actRecord, Date orderPaymentSuccessTime){
		Date startTime = actRecord.getStartTime();
		Date endTime = actRecord.getEndTime();
		if (startTime != null && orderPaymentSuccessTime.before(startTime)) {
			return false;
		}
		if (endTime != null && orderPaymentSuccessTime.after(endTime)) {
			return false;
		}
		return true;
	}

	// 提取通用的代码部分
	private AppUserPointRecord createPointRecord(JSONObject prop1Obj, BigDecimal amount, CardGroupOrderInfo orderInfos) {
		AppUserPointRecord pointRecord = new AppUserPointRecord();
		double pointRate = prop1Obj.getDouble("pointRate");
		Long points = amount.multiply(new BigDecimal(pointRate)).longValue();
		pointRecord.setType(prop1Obj.getString("pointType"));
		pointRecord.setChangePoint(points);
		pointRecord.setUserId(orderInfos.getUserId());
		pointRecord.setOrderId(orderInfos.getId());
		pointRecord.setOrderNo(orderInfos.getOrderNo());
		pointRecord.setCreateTime(new Date());
		pointRecord.setPointRate(pointRate);
		return pointRecord;
	}

	private boolean hasGroupSaleCode(CardGroupInfo cardGroupInfo){
		List<CodeRecordDTO> codeRecords = groupApiService.getRefCodeRecord(cardGroupInfo.getId(), null);
		boolean hasSaleCode = !CollectionUtils.isEmpty(codeRecords);
		if(hasSaleCode){
			return hasSaleCode;
		}
		//新版生态购
		GroupSaleCodeDTO saleCodeConfig = groupActService.getGroupSaleCodeConfig(cardGroupInfo.getId(),cardGroupInfo.getStatus()>=201);
		return saleCodeConfig.isHasBoxConfig();
	}

}
