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

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.constant.Constant;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.mapper.GoodsDonSkuMapper;
import com.cyksj.mapper.GroupsRelationMapper;
import com.cyksj.mapper.NanoUserQuotaMapper;
import com.cyksj.mapper.manage.cms.CmsUserMapper;
import com.cyksj.mapper.manage.distribute.DistributeWaitingSendPointsMapper;
import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
import com.cyksj.mapper.vip.RefundVipOrderDonMapper;
import com.cyksj.mapper.vip.VipOrderDonMapper;
import com.cyksj.mapper.vip.VipUserMapper;
import com.cyksj.model.entity.*;
import com.cyksj.model.manage.views.GroupsRelationView;
import com.cyksj.model.request.OrderRefundReq;
import com.cyksj.service.coin.UserGalaxyCoinService;
import com.cyksj.service.mange.vip.CmsVipOrderService;
import com.cyksj.service.order.OrderRefundService;
import com.cyksj.service.relation.GroupRelationClearService;
import com.cyksj.service.user.UserBenefitsService;
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 org.springframework.stereotype.Service;

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

/**
 * 项目名: yhlxj2
 * 文件名: CmsVipOrderServiceImpl
 * 创建者: JavaZou
 * 创建时间:2025/5/13 16:40
 */
@Service
@RequiredArgsConstructor
public class CmsVipOrderServiceImpl implements CmsVipOrderService {
	private final RefundVipOrderDonMapper refundVipOrderDonMapper;

	private final OrderRefundService orderRefundService;

	private final VipOrderDonMapper vipOrderDonMapper;

	private final VipUserMapper vipUserMapper;

	private final GroupsRelationMapper relationMapper;

	private final DistributeWaitingSendPointsMapper distributeWaitingSendPointsMapper;

	private final GroupRelationClearService groupRelationClearService;

	private final UserBenefitsService userBenefitsService;

	private final UserBindRelationService userBindRelationService;

	private final UserDistributeMapper userDistributeMapper;

	private final CmsUserMapper cmsUserMapper;

	private final NanoUserQuotaMapper nanoUserQuotaMapper;

	private final UserGalaxyCoinService userGalaxyCoinService;

	private final BeanSearcher beanSearcher;

	private final GoodsDonSkuMapper skuMapper;

	@Override
	public void refundOrders(OrderRefundReq refundReq) throws Exception {
		VipOrderDon orderDon = vipOrderDonMapper.selectById(refundReq.getOrderId());
		if (StrUtil.isEmpty(refundReq.getRefundType())) {
			refundReq.setRefundType("money");
		}
		Long adminId = refundReq.getAdminId();
		Optional.ofNullable(cmsUserMapper.selectById(adminId)).ifPresent(cmsUser -> refundReq.setOperator(cmsUser.getNickname()));
		String refundType = refundReq.getRefundType();
		//校验订单是否符合退款
		checkOrderRefund(orderDon, refundReq);
		//调用第三方接口退款
		String outNo = StrUtil.EMPTY;
		if (refundReq.getRefundMoney() != null && refundReq.getRefundMoney().compareTo(BigDecimal.ZERO) > 0) {
			outNo = orderRefundService.vipCenterRefund(refundReq, orderDon);
		}
		orderDon.setRefundDesc(refundReq.getRefundDesc());
		//记录退款信息
		commonRefund(orderDon, refundReq.getRefundMoney(), refundReq.getOperator(), outNo, refundType, refundReq.getIsOnly(), refundReq.getRefundBalance(), refundReq.getChatImg(), refundReq.getDeductBalance());
		//修改订单状态
		orderDon.setStatus(VipOrderDon.Status.refund);
		vipOrderDonMapper.updateById(orderDon);
	}

	private void commonRefund(VipOrderDon orderDon, BigDecimal refundMoney, String operator, String outNo, String refundType, Boolean isOnly, BigDecimal refundBalance, String chatImg, BigDecimal deductBalance) {
		//记录退款
		recordRefundOrder(orderDon, outNo, refundMoney, refundBalance, operator, chatImg, refundType);
		//退等比例
		if (isOnly != null && isOnly) {
			userBenefitsService.addUserBalance(orderDon.getUserId(), refundBalance, UserBalanceSourceRecord.Source.vip_refund, null, orderDon.getId(), orderDon.getPayTitle() + UserBalanceSourceRecord.Source.vip_refund.getDesc(), true);
			BigDecimal orderDonRefundBalance = Optional.ofNullable(orderDon.getRefundBalance()).orElse(BigDecimal.ZERO);
			orderDon.setRefundBalance(orderDonRefundBalance.add(refundBalance));
		}
		//若存在余额支付，退还余额
//		if (isOnly == null && orderDon.getBalance().compareTo(BigDecimal.ZERO) > 0) {
//			BigDecimal addBalance = orderDon.getBalance();
//			//需额外扣除余额
//			if (deductBalance != null && deductBalance.compareTo(BigDecimal.ZERO) > 0) {
//				addBalance = addBalance.subtract(deductBalance);
//			}
//			userBenefitsService.addUserBalance(orderDon.getUserId(), addBalance, UserBalanceSourceRecord.Source.vip_refund, null, orderDon.getId(), orderDon.getPayTitle() + UserBalanceSourceRecord.Source.vip_refund.getDesc(), true);
//		}
		//是否全额退款
//		BigDecimal orderDonRefundMoney = Optional.ofNullable(orderDon.getRefundMoney()).orElse(BigDecimal.ZERO);
//		BigDecimal orderDonRefundBalance = Optional.ofNullable(orderDon.getRefundBalance()).orElse(BigDecimal.ZERO);
//		if (orderDonRefundMoney.add(orderDonRefundBalance).compareTo(orderDon.getMoney().add(Optional.ofNullable(orderDon.getBalance()).orElse(BigDecimal.ZERO))) == 0) {
//			//是否使用银河币支付
//			OrderDonGalaxyCoinRecord orderDonGalaxyCoinRecord = orderDonGalaxyCoinRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonGalaxyCoinRecord.class)
//					.eq(OrderDonGalaxyCoinRecord::getSource, OrderDonGalaxyCoinRecord.Source.vip.ordinal())
//					.eq(OrderDonGalaxyCoinRecord::getOrderId, orderDon.getId())
//					.last("limit 1"));
//			if (orderDonGalaxyCoinRecord != null) {
//				//有效时，返还银河币 并记录
//				userGalaxyCoinService.recordOrderRefundGalaxyCoinIfValid(orderDon.getId(), orderDonGalaxyCoinRecord.getUserId(), orderDonGalaxyCoinRecord.getGalaxyCoin().abs(), OrderDonGalaxyCoinRecord.Source.vip);
//			}
//		}
		//扣除 该笔订单产生的返现银河币
		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) > 0) {
			userGalaxyCoinService.subOrderGenerateGalaxyCoin(orderDon.getId(), OrderDonGalaxyCoinRecord.Source.vip);
		}
		//余额现金混合退款
		if (OrderRefundReq.RefundType.bxj.name().equals(refundType)) {
			userBenefitsService.addUserBalance(orderDon.getUserId(), refundBalance, UserBalanceSourceRecord.Source.vip_refund, null, orderDon.getId(), orderDon.getPayTitle() + UserBalanceSourceRecord.Source.vip_refund.getDesc(), true);
		}

		if (VipOrderDon.Type.BALANCE.getType().equals(refundType)) {
			if (isOnly == null && orderDon.getMoney().compareTo(BigDecimal.ZERO) > 0) {
				userBenefitsService.addUserBalance(orderDon.getUserId(), refundMoney, UserBalanceSourceRecord.Source.refund, null, orderDon.getId(), orderDon.getPayTitle() + UserBalanceSourceRecord.Source.vip_refund.getDesc(), true);
			}
		}

		//扣除会员时长
		List<Long> userIdList = userBindRelationService.getRelationUserIdList(orderDon.getUserId(), null);
		VipUser vipUser = vipUserMapper.selectOne(Wrappers.lambdaQuery(VipUser.class)
				.in(VipUser::getUserId, userIdList)
				.last("limit 1"));
		if (vipUser != null) {
			int offsetMonths = orderDon.getNum();
			Date expiryTime = vipUser.getExpiryTime();
			DateTime subExpiryTime = DateUtil.offsetMonth(expiryTime, -offsetMonths);
			//主订单退款
			if (orderDon.getOrderType() == 1) {
				Date remainExpiryTime = subExpiryTime;
				Integer extendsDays = orderDon.getExtendsDays();
				DateTime now = DateTime.now();
				if (remainExpiryTime.compareTo(now) > 0 && extendsDays > 0) {
					subExpiryTime = DateUtil.offsetDay(subExpiryTime, -extendsDays);
				}
			}
			//若会员过期清除镜像user
			vipUser.setExpiryTime(subExpiryTime);
			clearVipMirrorUser(userIdList, subExpiryTime);
			vipUserMapper.updateById(vipUser);
		}
		if (StrUtil.isNotBlank(refundType) && !refundType.equals(VipOrderDon.Type.BALANCE.getType())) {
			//分销提成积分扣除
			deductVipDsPoints(orderDon);
		}

		GroupsRelationView groupsRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder().field(GroupsRelationView::getGoodsId, Constant.NANO_GOODS_ID).field(GroupsRelationView::getUserId, userIdList).op(Operator.InList).field(GroupsRelationView::getIsVip, Boolean.TRUE).build());
		if (groupsRelationView != null) {
			Long relationId = groupsRelationView.getId();
			NanoUserQuota nanoUserQuota = nanoUserQuotaMapper.selectOne(Wrappers.lambdaQuery(NanoUserQuota.class).eq(NanoUserQuota::getRelationId, relationId).last("limit 1"));
			if (nanoUserQuota != null) {
				GoodsDonSku sku = skuMapper.selectById(groupsRelationView.getSkuId());
				Integer offsetNum = orderDon.getNum() * sku.getNanoQuota();
				nanoUserQuota.setTotalQuota(nanoUserQuota.getTotalQuota() <= offsetNum ? nanoUserQuota.getTotalQuota() : nanoUserQuota.getTotalQuota() - offsetNum);
				nanoUserQuota.setRemainingQuota(nanoUserQuota.getRemainingQuota() < offsetNum ? 0 : nanoUserQuota.getRemainingQuota() - offsetNum);
				nanoUserQuotaMapper.updateById(nanoUserQuota);
			}
		}
	}

	private void deductVipDsPoints(VipOrderDon orderDon) {
		if (orderDon.getIsDistribute()) {
			DistributeWaitingSendPoints distributeWaitingSendPoints = distributeWaitingSendPointsMapper.selectOne(Wrappers.lambdaQuery(DistributeWaitingSendPoints.class).eq(DistributeWaitingSendPoints::getOrderId, orderDon.getId()).eq(DistributeWaitingSendPoints::getIsVip, Boolean.TRUE).last("limit 1"));
			if (distributeWaitingSendPoints != null) {
				BigDecimal money = orderDon.getMoney();
				BigDecimal refundMoney = orderDon.getRefundMoney();
				//已发送 发送中 部分 全额退款
				DistributeWaitingSendPoints.Status sendStatus = distributeWaitingSendPoints.getSendStatus();
				BigDecimal points = distributeWaitingSendPoints.getPoints();
				if (sendStatus == DistributeWaitingSendPoints.Status.waiting) {
					Integer thisGoodsRate = distributeWaitingSendPoints.getRate();
					if (thisGoodsRate == null || thisGoodsRate == 0) {
						thisGoodsRate = Optional.ofNullable(userDistributeMapper.getDistributeGoodsRateByUidAndGid(orderDon.getUserId(), orderDon.getGoodsId())).orElse(0);
					}
					if (refundMoney.compareTo(money) == 0) {
						//待发送状态 全额退款
						distributeWaitingSendPoints.setSendStatus(DistributeWaitingSendPoints.Status.close);
						distributeWaitingSendPoints.setRefundPoints(points);
						distributeWaitingSendPoints.setPoints(BigDecimal.ZERO);
						distributeWaitingSendPointsMapper.updateById(distributeWaitingSendPoints);
						return;
					}
					if (thisGoodsRate > 0) {
						BigDecimal refundRate = refundMoney.divide(money, 2, RoundingMode.DOWN);
						//退掉比例的提成
						BigDecimal needSubPoints = points.multiply(refundRate);
						distributeWaitingSendPoints.setRefundPoints(needSubPoints);
						//剩余积分
						BigDecimal remainPoints = points.subtract(needSubPoints);
						distributeWaitingSendPoints.setPoints(remainPoints);
						//原先获取积分也扣除
						if (distributeWaitingSendPoints.getOriPoints().compareTo(BigDecimal.ZERO) > 0) {
							BigDecimal oriNeedSubPoints = distributeWaitingSendPoints.getOriPoints().multiply(refundRate);
							distributeWaitingSendPoints.setOriPoints(distributeWaitingSendPoints.getOriPoints().subtract(oriNeedSubPoints));
						}
						distributeWaitingSendPointsMapper.updateById(distributeWaitingSendPoints);
					}
				} else if (sendStatus == DistributeWaitingSendPoints.Status.success) {
					//已发送的提成 部分退款 全额退款 需要扣除用户积分
					//扣除固定推广者积分
					Integer thisGoodsRate = distributeWaitingSendPoints.getRate();
					if (thisGoodsRate == null || thisGoodsRate == 0) {
						thisGoodsRate = Optional.ofNullable(userDistributeMapper.getDistributeGoodsRateByUidAndGid(orderDon.getUserId(), orderDon.getGoodsId())).orElse(0);
					}
					if (thisGoodsRate > 0) {
						BigDecimal refundRate = refundMoney.divide(money, 2, RoundingMode.DOWN);
						//退掉比例的提成
						BigDecimal needSubPoints = points.multiply(refundRate);
						userBenefitsService.deductDistributePoints(orderDon.getId(), distributeWaitingSendPoints.getSharedId(), needSubPoints);
						//部分退款
						distributeWaitingSendPoints.setRefundPoints(needSubPoints);
						distributeWaitingSendPoints.setPoints(points.subtract(needSubPoints));
						//原先获取积分也扣除
						if (distributeWaitingSendPoints.getOriPoints().compareTo(BigDecimal.ZERO) > 0) {
							BigDecimal oriNeedSubPoints = distributeWaitingSendPoints.getOriPoints().multiply(refundRate);
							distributeWaitingSendPoints.setOriPoints(distributeWaitingSendPoints.getOriPoints().subtract(oriNeedSubPoints));
						}
						distributeWaitingSendPointsMapper.updateById(distributeWaitingSendPoints);
					}

				}
			}
		}
	}

	private void recordRefundOrder(VipOrderDon orderDon, String outRefundNo, BigDecimal refundMoney, BigDecimal refundBalance, String operator, String chatImg, String refundType) {
		RefundVipOrderDon refund = new RefundVipOrderDon();
		refund.setOrderId(orderDon.getId());
		refund.setOutRefundNo(outRefundNo);
		refund.setTotalFee(orderDon.getMoney());
		refund.setRefundDesc(orderDon.getRefundDesc());
		//退款金额
		refund.setRefundFee(refundMoney);
		refund.setUserId(orderDon.getUserId());
		refund.setGoodsTitle(orderDon.getPayTitle());
		refund.setRefundMethod(orderDon.getType().name());
		refund.setOperator(operator);
		refund.setChatImg(chatImg);
		//退款方式
		if (StrUtil.isNotBlank(refundType) && refundType.equals(VipOrderDon.Type.BALANCE.getType())) {
			refund.setRefundMethod(refundType);
			refund.setRefundFee(orderDon.getRefundBalance());
		}
		//余额现金退款
		if (OrderRefundReq.RefundType.bxj.name().equals(refundType)) {
			refund.setRefundMethod(OrderRefundReq.RefundType.bxj.name());
			refund.setRefundBalance(refundBalance);
		}
		refundVipOrderDonMapper.insert(refund);
	}

	private void checkOrderRefund(VipOrderDon orderDon, OrderRefundReq refundReq) {
		if (orderDon.getStatus()!= VipOrderDon.Status.complete) {
			throw BusinessRuntimeException.getInstance("订单状态异常");
		}
		Long userId = orderDon.getUserId();
		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
		//会员是否已过期
		VipUser vipUser = vipUserMapper.selectOne(Wrappers.lambdaQuery(VipUser.class)
				.in(VipUser::getUserId, userIdList)
				.gt(VipUser::getExpiryTime, DateTime.now())
				.last("limit 1"));
		if (vipUser == null) {
			throw BusinessRuntimeException.getInstance("用户会员已过期，无法退款");
		}
		String refundType = refundReq.getRefundType();
		BigDecimal refundMoney = refundReq.getRefundMoney();
		BigDecimal refundBalance = refundReq.getRefundBalance();
		BigDecimal money = orderDon.getMoney();
		BigDecimal balance = orderDon.getBalance();
		BigDecimal orderDonRefundMoney = Optional.ofNullable(orderDon.getRefundMoney()).orElse(BigDecimal.ZERO);
		BigDecimal orderDonRefundBalance = Optional.ofNullable(orderDon.getRefundBalance()).orElse(BigDecimal.ZERO);
		//余额退款
		if (OrderDon.Type.BALANCE.getType().equals(refundType)) {
			refundMoney = orderDonRefundBalance.add(refundMoney);
			if (VipOrderDon.Type.BALANCE != orderDon.getType() && refundMoney.compareTo(money) > 0) {
				throw BusinessRuntimeException.getInstance("退款余额大于订单支付金额");
			}
			orderDon.setRefundBalance(refundMoney);
		} else if (OrderRefundReq.RefundType.bxj.name().equals(refundType)) {
			//该订单实际可抵扣金额 可退成余额
			BigDecimal actuallyDeductMoney = Optional.ofNullable(orderDon.getActuallyDeductMoney()).orElse(BigDecimal.ZERO);
			balance = balance.add(actuallyDeductMoney).add(money);
			refundBalance = refundBalance.add(orderDonRefundBalance);
			if (refundBalance.compareTo(balance) > 0) {
				throw BusinessRuntimeException.getInstance("退款余额大于订单总金额");
			}
			orderDon.setRefundBalance(refundBalance);

			refundMoney = orderDonRefundMoney.add(refundMoney);
			if (refundMoney.compareTo(money) > 0) {
				throw BusinessRuntimeException.getInstance("退款金额大于订单支付金额");
			}
			orderDon.setRefundMoney(refundMoney);
		}else {
			//退金额
			refundMoney = orderDonRefundMoney.add(refundMoney);
			if (refundMoney.compareTo(money) > 0) {
				throw BusinessRuntimeException.getInstance("退款金额大于订单支付金额");
			}
			orderDon.setRefundMoney(refundMoney);
		}
	}

	/**
	 * 整理会员车票时长
	 * 过期清除镜像user
	 */
	private void clearVipMirrorUser(List<Long> userIds, Date expiryTimeAfterSub) {
		Boolean overdue = expiryTimeAfterSub.before(DateTime.now());
		List<GroupsRelation> groupsRelations = relationMapper.selectList(Wrappers.lambdaQuery(GroupsRelation.class)
				.in(GroupsRelation::getUserId, userIds)
				.eq(GroupsRelation::getIsVip, Boolean.TRUE));
		groupsRelations.forEach(ticket -> {
			if (overdue) {
				//清除车票
				groupRelationClearService.clearTicket(ticket, UserTicketClearedRecord.Source.vip_refund);
				return;
			}
			ticket.setExpiryTime(expiryTimeAfterSub);
			relationMapper.updateById(ticket);
		});
	}
}
