package com.cyksj.service.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.*;
import com.cyksj.mapper.sys.SysConfigMapper;
import com.cyksj.mapper.vip.VipGoodsSkuMapper;
import com.cyksj.model.dto.VipDeductDto;
import com.cyksj.model.entity.*;
import com.cyksj.model.manage.views.GroupsRelationView;
import com.cyksj.model.response.VipUserPageResp;
import com.cyksj.service.user.UserBindRelationService;
import com.cyksj.service.vip.VipFrontService;
import com.ejlchina.searcher.BeanSearcher;
import com.ejlchina.searcher.param.Operator;
import com.ejlchina.searcher.util.MapUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 项目名: yhlxj2
 * 文件名: VipFrontServiceImpl
 * 创建者: JavaZou
 * 创建时间:2025/5/15 16:00
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class VipFrontServiceImpl implements VipFrontService {
	private final SysConfigMapper sysConfigMapper;

	private final VipGoodsSkuMapper vipGoodsSkuMapper;

	private final UserBindRelationService userBindRelationService;

	private final BeanSearcher beanSearcher;

	private final GoodsDonSkuMapper skuMapper;

	private final ChatgptUserMapper chatgptUserMapper;

	private final OrderDonRenewRecordMapper orderDonRenewRecordMapper;

	private final ClaudeUserMapper claudeUserMapper;

	private final OrderDonMapper orderDonMapper;

	@Override
	public void fillVipInfo(long userId, VipUserPageResp vipUserPageResp) {
		SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.VIP_FEE_KEY).last("limit 1"));
		if (sysConfig != null && StrUtil.isNotBlank(sysConfig.getSysValue())) {
			vipUserPageResp.setVipFee(BigDecimal.valueOf(Integer.parseInt(sysConfig.getSysValue())));
		}
		//可抵扣价格
		BigDecimal deductMoney = BigDecimal.ZERO;
		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
		List<Long> vipSkuIds = vipGoodsSkuMapper.selectList(null).stream().map(VipGoodsSku::getSkuId).collect(Collectors.toList());
		//可有抵扣车票
		DateTime now = DateTime.now();
		Number count = beanSearcher.searchCount(GroupsRelationView.class, MapUtils.builder().field(GroupsRelationView::getUserId, userIdList).op(Operator.InList).field(GroupsRelationView::getSkuId, vipSkuIds).op(Operator.InList).field(GroupsRelationView::getExpiryTime, now).op(Operator.GreaterThan).build());
		//可抵扣车票
		if (count.intValue() > 0) {
			//处理vip抵扣金额
			VipDeductDto vipDeductDto = commonHandleVipDeductMoney(userIdList, vipSkuIds);
			deductMoney = vipDeductDto.getDeductMoney();
			vipUserPageResp.setRelationUserViews(vipDeductDto.getRelationUserViews());
		}
		vipUserPageResp.setDeductMoney(deductMoney);
	}

	/**
	 * 检查用户并获取订单抵扣金额
	 */
	@Override
	public VipDeductDto checkAndGetOrderDeductMoney(Long userId) {
		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
		List<Long> vipSkuIds = vipGoodsSkuMapper.selectList(null).stream().map(VipGoodsSku::getSkuId).collect(Collectors.toList());
		Number count = beanSearcher.searchCount(GroupsRelationView.class, MapUtils.builder()
				.field(GroupsRelationView::getUserId, userIdList).op(Operator.InList)
				.field(GroupsRelationView::getSkuId, vipSkuIds).op(Operator.InList)
				.field(GroupsRelationView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan)
				.field(GroupsRelationView::getIsVip, false)
				.build());
		if (count.intValue() == 0) {
			throw BusinessRuntimeException.getInstance("暂无可抵扣AI车票");
		}
		VipDeductDto vipDeductDto = commonHandleVipDeductMoney(userIdList, vipSkuIds);
		return vipDeductDto;
	}


	private BigDecimal getVipMoney() {
		SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.VIP_FEE_KEY).last("limit 1"));
		if (sysConfig == null || StrUtil.isEmpty(sysConfig.getSysValue())) {
			throw BusinessRuntimeException.getInstance("系统异常");
		}
		BigDecimal vipFee = BigDecimal.valueOf(Long.valueOf(sysConfig.getSysValue()));
		return vipFee;
	}

	/**
	 * 统一处理vip抵扣金额
	 */
	public VipDeductDto commonHandleVipDeductMoney(List<Long> userIdList, List<Long> vipSkuIds) {
		VipDeductDto vipDeductDto = new VipDeductDto();
		DateTime now = DateTime.now();
		List<Long> deductRelationIds = new ArrayList<>();
		BigDecimal deductMoney = BigDecimal.ZERO;
		BigDecimal vipMoney = getVipMoney();
		List<GroupsRelationView> relations = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
				.field(GroupsRelationView::getSkuId, vipSkuIds).op(Operator.InList)
				.field(GroupsRelationView::getUserId, userIdList).op(Operator.InList)
				.field(GroupsRelationView::getIsVip, false)
				.field(GroupsRelationView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan)
				.orderBy(GroupsRelationView::getExpiryTime).desc()
				.build());
		Set<Long> deductSkuIds = null;
		List<GroupsRelationView> deductRelations = null;
		for (GroupsRelationView relation : relations) {
			if (deductSkuIds == null) {
				deductSkuIds = new HashSet<>();
			}
			if (deductRelations == null) {
				deductRelations = new ArrayList<>();
			}
			Long vipSkuId = relation.getSkuId();
			if (deductSkuIds.contains(vipSkuId)) {
				continue;
			}
			deductSkuIds.add(vipSkuId);
			Long goodsId = relation.getGoodsId();
			Long relationId = relation.getId();
			Date relationExpiryTime = relation.getExpiryTime();
			//GPT
			if (goodsId == Constant.GPT_PLUS_GID) {
				ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class).eq(ChatgptUser::getRelationId, relationId).last("limit 1"));
				if (chatgptUser != null) {
					//获取抵扣金额
					deductMoney = deductMoney.add(getFinalDeductMoney(relationId, relation.getSkuId(), chatgptUser.getRenewSkuId(), chatgptUser.getRenewOrderId(), chatgptUser.getRenewExpiryTime(), relation.getStartTime(), relationExpiryTime, now, userIdList));
				}
			} else if (goodsId == Constant.CLAUDE_PRO_GID) {
				ClaudeUser claudeUser = claudeUserMapper.selectOne(Wrappers.lambdaQuery(ClaudeUser.class).eq(ClaudeUser::getRelationId, relationId).last("limit 1"));
				if (claudeUser != null) {
					//获取抵扣金额
					deductMoney = deductMoney.add(getFinalDeductMoney(relationId, relation.getSkuId(), claudeUser.getRenewSkuId(), claudeUser.getRenewOrderId(), claudeUser.getRenewExpiryTime(), relation.getStartTime(), relationExpiryTime, now, userIdList));
				}
			} else {
				//该车票抵扣金额
				deductMoney = deductMoney.add(getDeductMoneyFromTicket(vipSkuId, now, relation.getId(), relation.getStartTime(), relationExpiryTime));
			}
			deductRelationIds.add(relationId);
			//可抵扣车票
			deductRelations.add(relation);
			//超出可抵扣的金额 直接返回
			if (deductMoney.compareTo(vipMoney) >= 0) {
				deductMoney = vipMoney;
				break;
			}
		}
		vipDeductDto.setDeductMoney(deductMoney);
		vipDeductDto.setDeductRelationIds(deductRelationIds);
		vipDeductDto.setRelationUserViews(deductRelations);
		return vipDeductDto;
	}

	/**
	 * 获取最终抵扣金额
	 */
	public BigDecimal getFinalDeductMoney(Long relationId, Long relationSkuId, Long renewSkuId, Long renewOrderId, Date renewExpiryTime, Date relationStartTime, Date relationExpiryTime, DateTime now, List<Long> userIdList) {
		BigDecimal deductMoney = BigDecimal.ZERO;
		//一个月当30天算单价 往上取整
		//续费规格
		if (renewSkuId != null) {
			OrderDon renewOrderDon = orderDonMapper.selectById(renewOrderId);
			GoodsDonSku sku = skuMapper.selectById(renewSkuId);
			Long betweenDay = DateUtil.betweenDay(now, renewExpiryTime, false) + 1;
			//当天购买的按规格原价抵扣
			if (now.toDateStr().equals(DateUtil.format(renewOrderDon.getCreatedTime(), "yyyy-MM-dd"))) {
				deductMoney = deductMoney.add(sku.getPrice());
			} else {
				BigDecimal single = sku.getPrice().divide(BigDecimal.valueOf(sku.getMonths()).multiply(BigDecimal.valueOf(30)), 0, RoundingMode.UP);
				//该车票抵扣金额
				BigDecimal renewDeductMoney = single.multiply(BigDecimal.valueOf(betweenDay));
				log.info("车票id:{}目前续费升级规格可抵扣的金额为：{}", relationId, renewDeductMoney);
				deductMoney = deductMoney.add(renewDeductMoney);
			}
			relationExpiryTime = DateUtil.offsetDay(relationExpiryTime, -betweenDay.intValue());
			//上一个续费升级规格
			List<OrderDon> orderDOns = orderDonRenewRecordMapper.getOtherRenewSkus(renewOrderId, relationId, userIdList);
			for (OrderDon orderDOn : orderDOns) {
				Long skuId = orderDOn.getSkuId();
				sku = skuMapper.selectById(skuId);
				BigDecimal upDeductMoney = sku.getPrice();
				log.info("车票id:{}目前次一级规格：{}可抵扣的金额为：{}", relationId, sku.getSpecVal(), upDeductMoney);
				deductMoney = deductMoney.add(upDeductMoney);
				if (sku.getDays() != null) {
					relationExpiryTime = DateUtil.offsetDay(relationExpiryTime, -sku.getDays());
				} else {
					relationExpiryTime = DateUtil.offsetMonth(relationExpiryTime, -sku.getMonths());
				}
			}
		}
		if (relationExpiryTime.after(DateTime.now())) {
			//该车票抵扣金额
			BigDecimal deductMoneyFromTicket = getDeductMoneyFromTicket(relationSkuId, now, relationId, relationStartTime, relationExpiryTime);
			deductMoney = deductMoney.add(deductMoneyFromTicket);
		}
		log.info("车票id:{}最终到期时间为：{}车票可返回 抵扣金额:{}", relationId, DateUtil.format(relationExpiryTime, "yyyy-MM-dd HH:mm:ss"), deductMoney);
		return deductMoney;
	}

	/**
	 * 获取车票可抵扣金额
	 */
	public BigDecimal getDeductMoneyFromTicket(Long skuId, DateTime now, Long relationId, Date relationStartTime, Date relationExpiryTime) {
		GoodsDonSku sku = skuMapper.selectById(skuId);
		BigDecimal single = sku.getPrice().divide(BigDecimal.valueOf(sku.getMonths()).multiply(BigDecimal.valueOf(30)), 0, RoundingMode.UP);
		Long betweenDay = DateUtil.betweenDay(now, relationExpiryTime, false) + 1;
		//当天购买的按规格原价抵扣
		if (now.toDateStr().equals(DateUtil.format(relationStartTime, "yyyy-MM-dd"))) {
			//并且没有续费 且未扣时长
			if (DateUtil.betweenDay(DateUtil.offsetMonth(relationStartTime, 1), relationExpiryTime, true) == 0) {
				return sku.getPrice();
			}
		}
		//该车票抵扣金额
		BigDecimal deductMoney = single.multiply(BigDecimal.valueOf(betweenDay));
		return deductMoney;
	}
}
