package com.cyksj.service.order.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.mapper.GoodsDonSkuMapper;
import com.cyksj.mapper.GroupsRelationMapper;
import com.cyksj.mapper.OrderDonMapper;
import com.cyksj.mapper.UserBenefitsComboRelationRecordMapper;
import com.cyksj.mapper.channel.UserPayEquipmentAvailableBenefitsMapper;
import com.cyksj.mapper.channel.UserPayEquipmentReceiveBenefitsRecordMapper;
import com.cyksj.mapper.mirrorshop.UserMirrorShopMapper;
import com.cyksj.model.entity.*;
import com.cyksj.model.manage.views.GroupsRelationView;
import com.cyksj.model.views.RenewalView;
import com.cyksj.model.views.UserAvailableGoodsTicketView;
import com.cyksj.service.exchange.ExchangeCodeService;
import com.cyksj.service.order.UserRealOrderBenefitsService;
import com.cyksj.service.relation.GroupRelationClearService;
import com.cyksj.service.user.UserBindRelationService;
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.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
 *文件名: UserRealOrderBenefitsImpl
 *创建者: JavaZou
 *创建时间:2023/3/7 14:54
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class UserRealOrderBenefitsImpl implements UserRealOrderBenefitsService {
	private final GroupsRelationMapper groupsRelationMapper;

	private final BeanSearcher beanSearcher;

	private final ExchangeCodeService exchangeCodeService;

	private final GoodsDonSkuMapper goodsDonSkuMapper;

	private final UserPayEquipmentReceiveBenefitsRecordMapper receiveBenefitsRecordMapper;

	private final UserPayEquipmentAvailableBenefitsMapper availableBenefitsMapper;

	private final GroupRelationClearService groupRelationClearService;

	private final OrderDonMapper orderDonMapper;

	private final UserBenefitsComboRelationRecordMapper userBenefitsComboRelationRecordMapper;

	private final UserBindRelationService userBindRelationService;

	private final UserMirrorShopMapper userMirrorShopMapper;

	@Override
	public Boolean getPayRealGoodsBenefits(Long userId, Long orderId, Long yhsId, List<GoodsDonSku> skuIds) {
		Boolean isReceivedAll = true;
		log.info("用户:{}实物订单orderId:{}发货,兑换权益规格数量:{}", userId, orderId, skuIds.size());
		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
		for (GoodsDonSku sku : skuIds) {
			Long skuId = sku.getId();
			sku = goodsDonSkuMapper.selectById(skuId);
			Long goodsId = sku.getGoodsId();
			log.info("开始发放实物订单orderId:{}权益规格:{}", orderId, skuId);
//			List<GroupsRelationView> relationViewList = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
//					.field(GroupsRelationView::getGoodsId, goodsId)
//					.field(GroupsRelationView::getUserId, userId)
//					.field(GroupsRelationView::getStatus, GroupsRelation.Status.validity.name())
//					.build());
			List<GroupsRelationView> relationViewList = groupsRelationMapper.selectRelationByGoodsId(goodsId, userIdList, yhsId);
			//是否有该规格车票,若无直接发放车票
			if (CollUtil.isEmpty(relationViewList)) {
				log.info("用户userId:{}未有skuId:{}车票,获取对应车票", userId, sku.getId());
				//领取权益时，没有车票的用户自动上车，获得对应车票
				GroupsRelation relation = exchangeCodeService.getGroupTripsTicket(yhsId, sku, userId, null, OrderDon.Type.PAY_EQUIPMENT, null);
//				//多给三天
//				DateTime expiryTime = DateUtil.offsetDay(relation.getExpiryTime(), 3);
//				groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
//						.set(GroupsRelation::getExpiryTime, expiryTime)
//						.eq(GroupsRelation::getId, relation.getId()));
				saveReceiveBenefitsRecord(userId, skuId, orderId, relation.getOrderId(), relation.getId(), sku.getMonths(), sku.getDays(), 1);
				log.info("用户userId:{}获取对应skuId:{}车票成功", userId, sku.getId());
			} else if (relationViewList.size() == 1) {
				//若有且只有一张增加时长
				GroupsRelationView groupsRelationView = relationViewList.get(0);
				log.info("存在对应规格:{}的车票,增加车票:relationId:{}时长", sku.getId(), groupsRelationView.getId());
				Date expiryTime = groupsRelationView.getExpiryTime();
				if (expiryTime == null) {
					throw BusinessRuntimeException.getInstance("用户存在未发车的车票,请发车后再进行发货");
				}
				DateTime updateExpiryTime = DateUtil.offset(expiryTime, DateField.MONTH, sku.getMonths());
				groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
						.eq(GroupsRelation::getId, groupsRelationView.getId())
						.set(GroupsRelation::getExpiryTime, updateExpiryTime));
				groupsRelationView.setUpdateExpiryTime(updateExpiryTime);
				saveReceiveBenefitsRecord(userId, skuId, orderId, null, groupsRelationView.getId(), sku.getMonths(), sku.getDays(), 1);
			} else {
				//若有该规格多张车票,保存可获取的车票权益 以供用户自行选择
				saveAvailableBenefits(userId, skuId, orderId);
				if (isReceivedAll) {
					isReceivedAll = false;
				}
			}
		}
		return isReceivedAll;
	}

	@Override
	public void deductUserRealGoodsBenefits(Long orderId) {
		//是否存在该实物订单权益
		List<UserPayEquipmentReceiveBenefitsRecord> benefitsRecords = Optional.ofNullable(receiveBenefitsRecordMapper.selectList(Wrappers.lambdaQuery(UserPayEquipmentReceiveBenefitsRecord.class)
				.eq(UserPayEquipmentReceiveBenefitsRecord::getRealOrderId, orderId))).orElse(new ArrayList<>());
		benefitsRecords.forEach(benefitsRecord -> {
			//扣除领取的权益
			deductReceivedBenefits(benefitsRecord.getUserId(), benefitsRecord.getTicketOrderId(), benefitsRecord.getRelationId(), benefitsRecord.getMonths(), benefitsRecord.getDays());
			benefitsRecord.setStatusCode(0);
			receiveBenefitsRecordMapper.updateById(benefitsRecord);
		});
		//是否存在可领取的实物订单权益
		//删除其权益
		availableBenefitsMapper.update(null, Wrappers.lambdaUpdate(UserPayEquipmentAvailableBenefits.class)
				.set(UserPayEquipmentAvailableBenefits::getDeleted, false)
				.eq(UserPayEquipmentAvailableBenefits::getRealOrderId, orderId));
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public GroupsRelationView receiveRealGoodsBenefits(Long userId, Long benefitsId, Long goodsId, Long skuId, Long relationId) {
		//可获取的权益是否存在
		UserPayEquipmentAvailableBenefits availableBenefits = availableBenefitsMapper.selectById(benefitsId);
		if (availableBenefits == null) {
			throw BusinessRuntimeException.getInstance("可获取的权益不存在");
		}
		if (availableBenefits.getStatusCode() == 1) {
			throw BusinessRuntimeException.getInstance("已领取该权益");
		}
		if (!availableBenefits.getDeleted()) {
			throw BusinessRuntimeException.getInstance("购买的实物设备已退款,无法领取该权益");
		}
		if (!availableBenefits.getSkuId().equals(skuId)) {
			throw BusinessRuntimeException.getInstance("可领取的车票权益规格错误");
		}
		GroupsRelationView groupsRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder()
				.field(GroupsRelationView::getGoodsId, goodsId)
				.field(GroupsRelationView::getId, relationId)
				.field(GroupsRelationView::getStatus, GroupsRelation.Status.validity.name())
				.field(GroupsRelationView::getUserId, userId)
				.build());
		Optional.ofNullable(groupRelationClearService).ifPresentOrElse(ticket -> {
			Date expiryTime = groupsRelationView.getExpiryTime();
			if (expiryTime == null) {
				throw BusinessRuntimeException.getInstance("该车位暂未发车,请发车后再领取权益");
			}
			GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(skuId);
			if (goodsDonSku == null || !goodsDonSku.getGoodsId().equals(goodsId)) {
				throw BusinessRuntimeException.getInstance("");
			}
			//删除可领取的权益
			int update = availableBenefitsMapper.update(null, Wrappers.lambdaUpdate(UserPayEquipmentAvailableBenefits.class)
					.set(UserPayEquipmentAvailableBenefits::getStatusCode, 1)
					.set(UserPayEquipmentAvailableBenefits::getDeleted, false)
					.eq(UserPayEquipmentAvailableBenefits::getDeleted, true)
					.eq(UserPayEquipmentAvailableBenefits::getId, benefitsId));
			if (update != 1) {
				throw BusinessRuntimeException.getInstance("系统错误,请刷新页面重试");
			}
			DateTime updateExpiryTime;
			if (goodsDonSku.getDays() != null && goodsDonSku.getDays() > 0) {
				updateExpiryTime = DateUtil.offsetDay(expiryTime, goodsDonSku.getDays());
			} else {
				updateExpiryTime = DateUtil.offset(expiryTime, DateField.MONTH, goodsDonSku.getMonths());
			}
			updateExpiryTime = DateUtil.offsetDay(updateExpiryTime, 3);
			groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
					.eq(GroupsRelation::getId, groupsRelationView.getId())
					.eq(GroupsRelation::getUserId, userId)
					.set(GroupsRelation::getExpiryTime, updateExpiryTime));
			groupsRelationView.setUpdateExpiryTime(updateExpiryTime);
			//保存领取权益
			saveReceiveBenefitsRecord(userId, skuId, availableBenefits.getRealOrderId(), null, relationId, goodsDonSku.getMonths(), goodsDonSku.getDays(), 1);
		}, () -> {
			throw BusinessRuntimeException.getInstance("对应规格车票不存在");
		});
		return groupsRelationView;
	}

	@Override
	public List<UserAvailableGoodsTicketView> getAvailableBenefitsTickets(Long userId, Long orderId, String customId, Integer cmt) {
		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
		List<UserAvailableGoodsTicketView> ticketViews = beanSearcher.searchAll(UserAvailableGoodsTicketView.class, MapUtils.builder()
				.field(UserAvailableGoodsTicketView::getUserId, userIdList).op(Operator.InList)
				.field(UserAvailableGoodsTicketView::getDeleted, true)
				.field(UserAvailableGoodsTicketView::getRealOrderId, orderId)
				.build());
		MapBuilder builder = MapUtils.builder();
		if (cmt != null && cmt == 2 && StrUtil.isNotBlank(customId)) {
			UserMirrorShop userMirrorShop = userMirrorShopMapper.selectOne(Wrappers.lambdaQuery(UserMirrorShop.class)
					.eq(UserMirrorShop::getCustomId, customId)
					.last("limit 1"));
			if (userMirrorShop != null) {
				builder.field(RenewalView::getCmt, cmt).field(RenewalView::getYhsId, userMirrorShop.getId());
			}
		}
		if (cmt == null || cmt != 2) {
			builder.field(RenewalView::getCmt, 2).op(Operator.NotEqual);
		}
		ticketViews.forEach(ticket -> {
			List<GroupsRelationView> relationViewList = beanSearcher.searchAll(GroupsRelationView.class, builder
					.field(GroupsRelationView::getUserId, userIdList).op(Operator.InList)
					.field(GroupsRelationView::getGoodsId, ticket.getGoodsId())
					.field(GroupsRelationView::getStatus, GroupsRelation.Status.validity.name())
					.field(GroupsRelationView::getExpiryTime).op(Operator.NotNull)
					.build());
			ticket.setTicketList(relationViewList);
		});
		return ticketViews;
	}

	@Override
	public void sendUserBenefitsTicket(OrderDon orderDon, List<GoodsDonSku> goodsDonSkus) {
		Long orderId = orderDon.getId();
		Long userId = orderDon.getUserId();
		Long yhsId = orderDon.getYhsId();
		List<Long> relationIds = new ArrayList<>();
		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
		goodsDonSkus.forEach(sku -> {
			Long skuId = sku.getId();
			sku = goodsDonSkuMapper.selectById(skuId);
			Long goodsId = sku.getGoodsId();
			log.info("开始发放用户套餐优惠权益订单:{} 车票规格:{}", orderId, skuId);
			List<GroupsRelationView> relationViewList = groupsRelationMapper.selectRelationByGoodsId(goodsId, userIdList, yhsId);
			//是否有该规格车票,若无直接发放车票
			if (CollUtil.isEmpty(relationViewList)) {
				log.info("用户userId:{}未有skuId:{}车票,获取对应车票", userId, sku.getId());
				//领取权益时，没有车票的用户自动上车，获得对应车票
				GroupsRelation relation = exchangeCodeService.getGroupTripsTicket(yhsId, sku, userId, null, OrderDon.Type.PAY_EQUIPMENT, null);
				relationIds.add(relation.getId());
			} else if (relationViewList.size() == 1) {
				//若有且只有一张增加时长
				GroupsRelationView groupsRelationView = relationViewList.get(0);
				log.info("存在对应规格:{}的车票,增加车票:relationId:{}时长", sku.getId(), groupsRelationView.getId());
				Date expiryTime = groupsRelationView.getExpiryTime();
				if (expiryTime == null) {
					throw BusinessRuntimeException.getInstance("用户存在未发车的车票,请发车后再进行发货");
				}
				DateTime updateExpiryTime = DateUtil.offset(expiryTime, DateField.MONTH, sku.getMonths());
				groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
						.eq(GroupsRelation::getId, groupsRelationView.getId())
						.set(GroupsRelation::getExpiryTime, updateExpiryTime));
				groupsRelationView.setUpdateExpiryTime(updateExpiryTime);
				relationIds.add(groupsRelationView.getId());
			} else if (relationViewList.size() > 1) {
				UserPayEquipmentAvailableBenefits userPayEquipmentAvailableBenefits = new UserPayEquipmentAvailableBenefits()
						.setUserId(userId)
						.setSkuId(skuId)
						.setType(1)
						.setRealOrderId(orderDon.getId());
				availableBenefitsMapper.insert(userPayEquipmentAvailableBenefits);
			}
		});
		UserBenefitsComboRelationRecord userBenefitsComboRelationRecord = new UserBenefitsComboRelationRecord();
		userBenefitsComboRelationRecord.setOrderId(orderId);
		userBenefitsComboRelationRecord.setRelationIds(relationIds.toString());
		userBenefitsComboRelationRecord.setUserId(orderDon.getUserId());
		userBenefitsComboRelationRecordMapper.insert(userBenefitsComboRelationRecord);
	}

	/**
	 * 保存获取权益记录
	 */
	private void saveReceiveBenefitsRecord(Long userId, Long skuId, Long realOrderId, Long ticketOrderId, Long relationId, Integer months, Integer days, Integer statusCode) {
		UserPayEquipmentReceiveBenefitsRecord userPayEquipmentReceiveBenefitsRecord = new UserPayEquipmentReceiveBenefitsRecord()
				.setUserId(userId)
				.setSkuId(skuId)
				.setRealOrderId(realOrderId)
				.setTicketOrderId(ticketOrderId)
				.setRelationId(relationId)
				.setDays(days)
				.setMonths(months)
				.setStatusCode(statusCode);
		receiveBenefitsRecordMapper.insert(userPayEquipmentReceiveBenefitsRecord);
	}

	/**
	 * 保存用户可获取权益的车票
	 */
	public void saveAvailableBenefits(Long userId, Long skuId, Long realOrderId) {
		UserPayEquipmentAvailableBenefits userPayEquipmentAvailableBenefits = new UserPayEquipmentAvailableBenefits()
				.setUserId(userId)
				.setSkuId(skuId)
				.setRealOrderId(realOrderId);
		availableBenefitsMapper.insert(userPayEquipmentAvailableBenefits);
	}


	/**
	 * 扣除用户领取的权益
	 */
	private void deductReceivedBenefits(Long userId, Long ticketOrderId, Long relationId, Integer months, 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"));
		Date expiryTime = relation.getExpiryTime();
		if (relation == null) {
			return;
		}
		if (expiryTime == null) {
			//未发车直接清除车票
			groupRelationClearService.clearTicket(relation, UserTicketClearedRecord.Source.pay_equipment);
		} else {
			DateTime now = DateTime.now();
			Date finalDate;
			if (days != null && days > 0) {
				finalDate = DateUtil.offsetDay(expiryTime, -days);
			} else {
				finalDate = DateUtil.offset(expiryTime, DateField.MONTH, -months);
			}
			finalDate = DateUtil.offsetDay(finalDate, -3);
			if (now.isAfter(finalDate)) {
				//过期 直接清除车票
				groupRelationClearService.clearTicket(relation, UserTicketClearedRecord.Source.pay_equipment);
			} else {
				relation.setExpiryTime(finalDate);
				groupsRelationMapper.updateById(relation);
			}
		}
		Optional.ofNullable(ticketOrderId).ifPresent(selfOrderId -> {
			orderDonMapper.update(null, Wrappers.lambdaUpdate(OrderDon.class).eq(OrderDon::getId, selfOrderId)
					.set(OrderDon::getRefundMoney, BigDecimal.ZERO)
					.set(OrderDon::getStatus, OrderDon.Status.refund));
		});
	}
}
