package com.cyksj.service.invoice.impl;

import cn.hutool.core.collection.CollUtil;
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.OrderDonMapper;
import com.cyksj.mapper.UpgradeOrderDonMapper;
import com.cyksj.mapper.UserInvoiceApplyRecordMapper;
import com.cyksj.mapper.UserInvoiceOrderRelateMapper;
import com.cyksj.mapper.channel.ShopConfigMapper;
import com.cyksj.mapper.vip.VipOrderDonMapper;
import com.cyksj.model.dto.InvoiceOrderDto;
import com.cyksj.model.entity.*;
import com.cyksj.model.request.UserInvoiceOrderReq;
import com.cyksj.redis.RedisService;
import com.cyksj.service.invoice.UserInvoiceApplyRecordService;
import com.cyksj.service.user.UserBindRelationService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 项目名: yhlxj
 * 文件名: UserInvoiceServiceImpl
 * 创建者: JavaZou
 * 创建时间:2024/12/13 15:28
 */
@Service
@RequiredArgsConstructor
public class UserInvoiceApplyRecordServiceImpl implements UserInvoiceApplyRecordService {
	private final UserInvoiceApplyRecordMapper userInvoiceApplyRecordMapper;

	private final UserInvoiceOrderRelateMapper userInvoiceOrderRelateMapper;

	private final OrderDonMapper orderDonMapper;

	private final UserBindRelationService userBindRelationService;

	private final ShopConfigMapper shopConfigMapper;

	private final RedisService redisService;

	private final UpgradeOrderDonMapper upgradeOrderDonMapper;

	private final VipOrderDonMapper vipOrderDonMapper;

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public Long applyOrderInvoice(UserInvoiceOrderReq req) {
		Long userId = req.getUserId();
		String key = "invoice:key:" + userId;
		try {
			List<InvoiceOrderDto> orderDons = req.getOrderDons();
			if (CollUtil.isEmpty(orderDons)) {
				throw BusinessRuntimeException.getInstance("请选择对应订单");
			}
			String head = req.getHead();
			String taxNo = req.getTaxNo();
			String email = req.getEmail();
			String bank = req.getBank();
			String bankNo = req.getBankNo();
			if (StrUtil.hasEmpty(head, taxNo, email)) {
				throw BusinessRuntimeException.getInstance("请完成必填项");
			}
			if (!redisService.setNx(key, userId, 30l)) {
				throw BusinessRuntimeException.getInstance("正在提交中，请勿重复提交");
			}
			List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
			Map<Integer, List<InvoiceOrderDto>> ordersByType = orderDons.stream().collect(Collectors.groupingBy(InvoiceOrderDto::getType));
			Set<String> shopIdSet = new HashSet<>();
			UserInvoiceApplyRecord invoiceApplyRecord = new UserInvoiceApplyRecord();
			invoiceApplyRecord.setMoney(BigDecimal.ZERO);
			ordersByType.forEach((type, orders) -> {
				List<Long> orderIds = orders.stream().map(InvoiceOrderDto::getOrderId).collect(Collectors.toList());
				//订单里是否存在开过发票
				Integer selectCount = userInvoiceOrderRelateMapper.selectCount(Wrappers.lambdaQuery(UserInvoiceOrderRelate.class)
						.eq(UserInvoiceOrderRelate::getType, type)
						.in(UserInvoiceOrderRelate::getOrderId, orderIds));
				if (selectCount > 0) {
					throw BusinessRuntimeException.getInstance("您选择的订单存在开过发票，请刷新页面重新选择");
				}
				Integer selfOrderIdSize;
				if (type == 1) {
					//是否是自己订单
					List<OrderDon> orderDonList = orderDonMapper.selectList(Wrappers.lambdaQuery(OrderDon.class)
							.in(OrderDon::getId, orderIds)
							.in(OrderDon::getUserId, userIdList)
							.notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
							.select(OrderDon::getId, OrderDon::getMoney, OrderDon::getShopId));
					for (OrderDon o : orderDonList) {
						invoiceApplyRecord.setMoney(invoiceApplyRecord.getMoney().add(o.getMoney()));
						shopIdSet.add(o.getShopId());
					}
					selfOrderIdSize = orderDonList.size();
				} else if (type == 2) {
					List<UpgradeOrderDon> upgradeOrderDons = upgradeOrderDonMapper.selectList(Wrappers.lambdaQuery(UpgradeOrderDon.class)
							.in(UpgradeOrderDon::getId, orderIds)
							.in(UpgradeOrderDon::getUserId, userIdList)
							.notIn(UpgradeOrderDon::getStatus, Constant.noOrderAllStatus)
							.select(UpgradeOrderDon::getId, UpgradeOrderDon::getMoney, UpgradeOrderDon::getShopId));
					for (UpgradeOrderDon o : upgradeOrderDons) {
						invoiceApplyRecord.setMoney(invoiceApplyRecord.getMoney().add(o.getMoney()));
						shopIdSet.add(o.getShopId());
					}
					selfOrderIdSize = upgradeOrderDons.size();
				}else {
					//会员订单
					List<VipOrderDon> VipOrderDons = vipOrderDonMapper.selectList(Wrappers.lambdaQuery(VipOrderDon.class)
							.in(VipOrderDon::getId, orderIds)
							.in(VipOrderDon::getUserId, userIdList)
							.notIn(VipOrderDon::getStatus, Constant.noOrderAllStatus)
							.select(VipOrderDon::getId, VipOrderDon::getMoney, VipOrderDon::getShopId));
					for (VipOrderDon o : VipOrderDons) {
						invoiceApplyRecord.setMoney(invoiceApplyRecord.getMoney().add(o.getMoney()));
						shopIdSet.add(o.getShopId());
					}
					selfOrderIdSize = VipOrderDons.size();
				}
				if (selfOrderIdSize != orderIds.size()) {
					throw BusinessRuntimeException.getInstance("订单选择错误，请刷新页面重新选择");
				}
			});
			//是否是统一主体
			if (shopIdSet.size() > 1) {
				throw BusinessRuntimeException.getInstance("所选订单的支付主体不一致，请重新选择)");
			}
			invoiceApplyRecord.setHead(head);
			invoiceApplyRecord.setTaxNo(taxNo);
			invoiceApplyRecord.setUserId(userId);
			invoiceApplyRecord.setBank(bank);
			invoiceApplyRecord.setBankNo(bankNo);
			ShopConfig shopConfig = shopConfigMapper.selectOne(Wrappers.lambdaQuery(ShopConfig.class)
					.in(ShopConfig::getAppId, shopIdSet)
					.last("limit 1"));
			if (shopConfig == null) {
				throw BusinessRuntimeException.getInstance("申请发票错误，请联系客服处理");
			}
			invoiceApplyRecord.setZfbPayment(shopConfig.getPayment());
			invoiceApplyRecord.setEmail(email);
			userInvoiceApplyRecordMapper.insert(invoiceApplyRecord);

			//关联记录id
			Long recordId = invoiceApplyRecord.getId();
			userInvoiceOrderRelateMapper.batchInsert(recordId, userId, orderDons);
			return invoiceApplyRecord.getId();
		} finally {
			redisService.del(key);
		}
	}
}
