package com.cyksj.service.coin.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.PointsRecordConst;
import com.cyksj.mapper.OrderDonGalaxyCoinRecordMapper;
import com.cyksj.mapper.UserGalaxyCoinRecordMapper;
import com.cyksj.mapper.UserMapper;
import com.cyksj.model.entity.OrderDonGalaxyCoinRecord;
import com.cyksj.model.entity.User;
import com.cyksj.model.entity.UserGalaxyCoinRecord;
import com.cyksj.service.coin.UserGalaxyCoinService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;

/**
 * 项目名: yhlxj
 * 文件名: UserGalaxyCoinServiceImpl
 * 创建者: JavaZou
 * 创建时间:2025/7/1 15:29
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class UserGalaxyCoinServiceImpl implements UserGalaxyCoinService {
	private final UserGalaxyCoinRecordMapper userGalaxyCoinRecordMapper;

	private final UserMapper userMapper;

	private final OrderDonGalaxyCoinRecordMapper orderDonGalaxyCoinRecordMapper;

	@Override
	public void sendGalaxyCoinRecord(Long userId, Integer galaxyCoin, String remark, Boolean isLottery) {
		if (!isLottery) {
			sendGalaxyCoinHandle(userId, null, galaxyCoin, remark, true, true, null);
		}
	}

	/**
	 * @param isRecord  是否记录
	 * @param available 该笔银河币是否可用
	 */
	public void sendGalaxyCoinHandle(Long userId, Long orderId, Integer galaxyCoin, String remark, Boolean isRecord, Boolean available, OrderDonGalaxyCoinRecord.Source source) {
		//银河币为0不处理
		if (galaxyCoin == 0) {
			return;
		}
		while (true) {
			User user = userMapper.selectById(userId);
			if (user == null) {
				log.error("用户:{}不存在，无法发送银河币", userId);
				break;
			}
			BigDecimal userGalaxyCoin = user.getGalaxyCoin();
			if (galaxyCoin < 0 && userGalaxyCoin.compareTo(BigDecimal.ZERO) == 0) {
				log.info("用户：{}银河币数量为0，无法扣除", userId);
				break;
			}
			BigDecimal needHandleGalaxyCoin = userGalaxyCoin.add(BigDecimal.valueOf(galaxyCoin));
			BigDecimal finalRecordGalaxyCoin = BigDecimal.valueOf(galaxyCoin);
			//不足部分 只扣除用户已有的银河币
			if (needHandleGalaxyCoin.compareTo(BigDecimal.ZERO) < 0) {
				needHandleGalaxyCoin = BigDecimal.ZERO;
				//记录该笔银河币
				if (finalRecordGalaxyCoin.compareTo(BigDecimal.ZERO) < 0) {
					finalRecordGalaxyCoin = userGalaxyCoin.negate();
				} else finalRecordGalaxyCoin = userGalaxyCoin;
			}
			int update = userMapper.update(null, Wrappers.lambdaUpdate(User.class)
					.set(User::getGalaxyCoin, needHandleGalaxyCoin)
					.eq(User::getId, user.getId())
					.eq(User::getGalaxyCoin, userGalaxyCoin));
			if (update == 1) {
				if (isRecord) {
					recordUseRecord(orderId, userId, finalRecordGalaxyCoin, remark, available, source);
				}
				break;
			}
		}
	}

	/**
	 * 记录银河币详情
	 */
	@Override
	public void recordUseRecord(Long orderId, Long userId, BigDecimal galaxyCoin, String remark, Boolean available, OrderDonGalaxyCoinRecord.Source source) {
		UserGalaxyCoinRecord userGalaxyCoinRecord = new UserGalaxyCoinRecord();
		userGalaxyCoinRecord.setOrderId(orderId);
		userGalaxyCoinRecord.setUserId(userId);
		userGalaxyCoinRecord.setGalaxyCoin(galaxyCoin);
		userGalaxyCoinRecord.setRemainGalaxyCoin(userGalaxyCoinRecord.getGalaxyCoin());
		//退款类型
		if (StrUtil.equals(PointsRecordConst.ORDER_REFUND, remark)) {
			//90天
			userGalaxyCoinRecord.setExpiryTime(DateUtil.offsetDay(DateTime.now(), 90));
		} else {
			//年底失效
			userGalaxyCoinRecord.setExpiryTime(DateUtil.offsetMonth(DateTime.now(), 12));
		}
		//下单 标记该笔银河币记录为已使用
		//该银河币是否可用
		if (!available) {
			userGalaxyCoinRecord.setIsUsed(Boolean.TRUE);
			//下单时，剩余是0
			userGalaxyCoinRecord.setRemainGalaxyCoin(BigDecimal.ZERO);
		}
		if (source != null) {
			userGalaxyCoinRecord.setSource(source.ordinal());
		}
		userGalaxyCoinRecord.setRemark(remark);
		userGalaxyCoinRecordMapper.insert(userGalaxyCoinRecord);
	}

	@Override
	public void recordOrderRefundGalaxyCoinIfValid(Long orderId, Long userId, BigDecimal galaxyCoin, OrderDonGalaxyCoinRecord.Source source) {
		UserGalaxyCoinRecord userGalaxyCoinRecord = userGalaxyCoinRecordMapper.selectOne(Wrappers.lambdaQuery(UserGalaxyCoinRecord.class)
				.eq(UserGalaxyCoinRecord::getOrderId, orderId)
				.eq(UserGalaxyCoinRecord::getRemark, PointsRecordConst.ORDER)
				.last("limit 1"));
		if (userGalaxyCoinRecord == null) {
			log.info("订单:{}银河币使用记录不存在", orderId);
			return;
		}
		if (userGalaxyCoinRecord.getExpiryTime().compareTo(DateTime.now()) < 0) {
			log.info("该笔订单:{}银河币有效期:{}已过", orderId, userGalaxyCoinRecord.getExpiryTime());
			return;
		}
		//发送银河币
		sendGalaxyCoinHandle(userId, orderId, galaxyCoin.intValue(), PointsRecordConst.ORDER_REFUND, true, true, source);
	}

	@Override
	public void subOrderGenerateGalaxyCoin(Long orderId, OrderDonGalaxyCoinRecord.Source source) {
		UserGalaxyCoinRecord userGalaxyCoinRecord = userGalaxyCoinRecordMapper.selectOne(Wrappers.lambdaQuery(UserGalaxyCoinRecord.class)
				.eq(UserGalaxyCoinRecord::getOrderId, orderId)
				.eq(UserGalaxyCoinRecord::getSource, source.ordinal())
				.eq(UserGalaxyCoinRecord::getRemark, PointsRecordConst.ORDER_CASHBACK)
				.last("limit 1"));
		if (userGalaxyCoinRecord != null) {
			BigDecimal galaxyCoin = userGalaxyCoinRecord.getGalaxyCoin();
			//扣除记录 对应的银河币不可用
			log.info("订单退款，扣除该笔订单oid:{}返现的银河币", orderId);
			BigDecimal thisReturnRemainGalaxyCoin = userGalaxyCoinRecord.getRemainGalaxyCoin();
			//扣除其他
			if (thisReturnRemainGalaxyCoin.compareTo(galaxyCoin) < 0) {
				//银河币抵扣
				List<UserGalaxyCoinRecord> availableGalaxyCoinList = userGalaxyCoinRecordMapper.selectList(Wrappers.lambdaQuery(UserGalaxyCoinRecord.class)
						.eq(UserGalaxyCoinRecord::getUserId, userGalaxyCoinRecord.getUserId())
						.eq(UserGalaxyCoinRecord::getIsUsed, Boolean.FALSE)
						.gt(UserGalaxyCoinRecord::getExpiryTime, DateTime.now())
						.gt(UserGalaxyCoinRecord::getRemainGalaxyCoin, 0));
				//需要使用的银河币
				BigDecimal userFinalUseGalaxyCoin = galaxyCoin.subtract(thisReturnRemainGalaxyCoin);
				for (UserGalaxyCoinRecord galaxyCoinRecord : availableGalaxyCoinList) {
					if (userFinalUseGalaxyCoin.compareTo(BigDecimal.ZERO) <= 0) {
						break;
					}
					BigDecimal remainGalaxyCoin = galaxyCoinRecord.getRemainGalaxyCoin();
					Long galaxyCoinRecordId = galaxyCoinRecord.getId();
					//扣完
					if (remainGalaxyCoin.compareTo(userFinalUseGalaxyCoin) == 0) {
						//完全抵扣
						Integer update = deductUserGalaxyCoin(galaxyCoinRecordId, remainGalaxyCoin, remainGalaxyCoin, true);
						if (update == 1) {
							userFinalUseGalaxyCoin = BigDecimal.ZERO;
						}
					} else if (remainGalaxyCoin.compareTo(userFinalUseGalaxyCoin) < 0) {
						//不足以抵扣
						Integer update = deductUserGalaxyCoin(galaxyCoinRecordId, remainGalaxyCoin, remainGalaxyCoin, true);
						if (update == 1) {
							userFinalUseGalaxyCoin = userFinalUseGalaxyCoin.subtract(remainGalaxyCoin);
						}
					} else if (remainGalaxyCoin.compareTo(userFinalUseGalaxyCoin) > 0) {
						//足以抵扣
						Integer update = deductUserGalaxyCoin(galaxyCoinRecordId, userFinalUseGalaxyCoin, remainGalaxyCoin, false);
						if (update == 1) {
							userFinalUseGalaxyCoin = BigDecimal.ZERO;
						}
					}
				}
			}
			sendGalaxyCoinHandle(userGalaxyCoinRecord.getUserId(), orderId, galaxyCoin.negate().intValue(), PointsRecordConst.ORDER_REFUND_SUB, true, false, source);
			userGalaxyCoinRecord.setIsUsed(Boolean.TRUE);
			userGalaxyCoinRecordMapper.updateById(userGalaxyCoinRecord);
		}
	}

	/**
	 * 订单回调时，扣除已使用的银河币 并记录使用记录
	 */
	@Override
	public void handleUserGalaxyCoinOrderNotify(Long orderId, Long userId, String orderNo, OrderDonGalaxyCoinRecord.Source source) {
		//银河币使用记录
		OrderDonGalaxyCoinRecord orderDonGalaxyCoinRecord = orderDonGalaxyCoinRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonGalaxyCoinRecord.class)
				.eq(OrderDonGalaxyCoinRecord::getOrderNo, orderNo)
				.eq(OrderDonGalaxyCoinRecord::getSource, source.ordinal())
				.last("limit 1"));
		if (orderDonGalaxyCoinRecord != null) {
			//使用记录
			recordUseRecord(orderId, userId, orderDonGalaxyCoinRecord.getGalaxyCoin().negate(), PointsRecordConst.ORDER, false, source);
			orderDonGalaxyCoinRecord.setRefundGalaxyCoin(orderDonGalaxyCoinRecord.getGalaxyCoin());
			orderDonGalaxyCoinRecord.setOrderId(orderId);
			orderDonGalaxyCoinRecordMapper.updateById(orderDonGalaxyCoinRecord);
		}
	}

	/**
	 * 订单支付成功 返银河币
	 */
	@Override
	public void sendOrderCashback(Long orderId, Long userId, Integer galaxyCoin, String remark, OrderDonGalaxyCoinRecord.Source source) {
		sendGalaxyCoinHandle(userId, orderId, galaxyCoin, remark, true, true, source);
	}

	public void sendOrderGalaxyCloseOrder(Long orderId, Long userId, BigDecimal galaxyCoin, OrderDonGalaxyCoinRecord.Source source) {
		sendGalaxyCoinHandle(userId, orderId, galaxyCoin.intValue(), PointsRecordConst.ORDER_CLOSE, true, true, source);
	}

	private Integer deductUserGalaxyCoin(Long galaxyCoinRecordId, BigDecimal deductGalaxyCoin, BigDecimal remainGalaxyCoin, boolean isUsed) {
		Integer update = userGalaxyCoinRecordMapper.update(null, Wrappers.lambdaUpdate(UserGalaxyCoinRecord.class)
				.set(UserGalaxyCoinRecord::getRemainGalaxyCoin, remainGalaxyCoin.subtract(deductGalaxyCoin))
				.set(isUsed, UserGalaxyCoinRecord::getIsUsed, isUsed)
				.eq(UserGalaxyCoinRecord::getId, galaxyCoinRecordId)
				.eq(UserGalaxyCoinRecord::getIsUsed, Boolean.FALSE)
				.eq(UserGalaxyCoinRecord::getRemainGalaxyCoin, remainGalaxyCoin));
		if (update == 0) {
			log.info("此次扣除银河币错误，继续扣除");
		}
		return update;
	}
}
