package com.yiqi.recharge.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yiqi.common.core.page.TableDataInfo;
import com.yiqi.common.exception.ServiceException;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yiqi.app.domain.AppUser;
import com.yiqi.app.domain.AppUserBillMstr;
import com.yiqi.app.service.IAppUserBillMstrService;
import com.yiqi.app.service.IAppUserService;
import com.yiqi.common.core.domain.AuthHolder;
import com.yiqi.common.core.domain.PageVO;
import com.yiqi.common.enums.*;
import com.yiqi.common.exception.GlobalException;
import com.yiqi.common.utils.*;
import com.yiqi.common.utils.bean.BeanUtils;
import com.yiqi.order.domain.OrderRecharge;
import com.yiqi.order.domain.dto.OrderRechargeCreateDTO;
import com.yiqi.order.domain.dto.RechargeCardPayDTO;
import com.yiqi.order.service.IOrderRechargeService;
import com.yiqi.recharge.domain.RechargeCardBatchRecord;
import com.yiqi.recharge.domain.RechargePasswordCard;
import com.yiqi.recharge.domain.dto.*;
import com.yiqi.recharge.domain.dto.weapp.WeAppCardRecordByCardDTO;
import com.yiqi.recharge.domain.dto.weapp.WeAppCardRecordByUserDTO;
import com.yiqi.recharge.domain.vo.RechargeBalanceCountVO;
import com.yiqi.recharge.domain.vo.RechargeCardBillMstrQueryVO;
import com.yiqi.recharge.domain.vo.RechargePasswordCardQueryVO;
import com.yiqi.recharge.domain.vo.StoreCardStatisticsVO;
import com.yiqi.recharge.domain.vo.weapp.WeAppCardsInfoVO;
import com.yiqi.recharge.domain.vo.weapp.WeAppCardsUseRecordsVO;
import com.yiqi.recharge.mapper.RechargePasswordCardMapper;
import com.yiqi.recharge.service.IRechargeCardBatchRecordService;
import com.yiqi.recharge.service.IRechargePasswordCardService;
import com.yiqi.system.domain.SysStore;
import com.yiqi.system.service.ISysSettlementRateService;
import com.yiqi.system.service.ISysStoreService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 密码充值卡管理Service业务层处理
 *
 * @author xiaohei
 * @date 2023-08-29
 */
@Service
@Slf4j
public class RechargePasswordCardServiceImpl extends ServiceImpl<RechargePasswordCardMapper, RechargePasswordCard> implements IRechargePasswordCardService {

    @Autowired
    private ISysStoreService sysStoreService;
    @Autowired
    private IAppUserService appUserService;

    @Lazy
    @Autowired
    private IAppUserBillMstrService appUserBillMstrService;
    @Lazy
    @Autowired
    private IRechargeCardBatchRecordService rechargeCardBatchRecordService;
    @Autowired
    private OrderNoUtils orderNoUtils;
    @Autowired
    private IOrderRechargeService orderRechargeService;
    @Autowired
    private IAppUserBillMstrService billMstrOrderService;

    @Override
    public List<RechargePasswordCardQueryVO> selectRechargePasswordCardList(PageVO pageVO) {
        return baseMapper.selectUserRechargePasswordCardList(pageVO, AuthHolder.userId());
    }

    @Override
    public List<RechargePasswordCardQueryVO> selectRechargePasswordCardList(MemberCardQueryDTO memberCardQueryDTO) {
        return baseMapper.selectUserRechargePasswordCardList(memberCardQueryDTO, memberCardQueryDTO.getAppUserId());
    }

    @Override
    public int countRechargePasswordCardList(MemberCardQueryDTO memberCardQueryDTO) {
        return baseMapper.countRechargePasswordCardList(memberCardQueryDTO, memberCardQueryDTO.getAppUserId());
    }

    @Override
    public RechargePasswordCard selectTotalBalanceGroupByAppUser(Long appUserId) {
        return selectTotalBalanceGroupByAppUser(appUserId, null);
    }

    @Override
    public RechargePasswordCard selectTotalBalanceGroupByAppUser(Long appUserId, String orderType) {
        RechargePasswordCard rechargePasswordCard = baseMapper.selectTotalBalanceGroupByAppUser(appUserId, orderType);
        if (rechargePasswordCard != null) {
            rechargePasswordCard.setTotalBalance(rechargePasswordCard.getRechargeBalance().add(rechargePasswordCard.getGiveBalance()).add(rechargePasswordCard.getWelfareBalance()));
        } else {
            rechargePasswordCard = new RechargePasswordCard();
            rechargePasswordCard.setTotalBalance(BigDecimal.ZERO);
            rechargePasswordCard.setRechargeBalance(BigDecimal.ZERO);
            rechargePasswordCard.setGiveBalance(BigDecimal.ZERO);
            rechargePasswordCard.setWelfareBalance(BigDecimal.ZERO);
        }
        return rechargePasswordCard;
    }

    @Override
    public List<RechargeBalanceCountVO> getUserBalanceCountList(RechargeBalanceCountDTO rechargeBalanceCountDTO) {
        // 按分页查询用户
        List<RechargeBalanceCountVO> balanceCountVOS = baseMapper.findUserPageByBalance(rechargeBalanceCountDTO, SecurityUtils.getLoginUser().getSourceType(), SecurityUtils.getLoginUser().getOrgId());
        if (CollUtil.isEmpty(balanceCountVOS)) {
            return new ArrayList<>();
        }
        List<Long> userIdList = balanceCountVOS.stream().map(RechargeBalanceCountVO::getUserId).collect(Collectors.toList());

        // 通过用户id，查询余额
        Map<Long, RechargeBalanceCountVO> balanceCountMap = baseMapper.getBalanceCountListByUserIdList(userIdList, DateUtils.getNowDate())
                .stream().collect(Collectors.toMap(RechargeBalanceCountVO::getUserId, RechargeBalanceCountVO -> RechargeBalanceCountVO));
        // 查询全店的 总余额
        for (RechargeBalanceCountVO balanceCountVO : balanceCountVOS) {
            if (!balanceCountMap.containsKey(balanceCountVO.getUserId())) {
                continue;
            }
            balanceCountVO.setPointBalance(balanceCountMap.get(balanceCountVO.getUserId()).getPointBalance());
            balanceCountVO.setGiveBalance(balanceCountMap.get(balanceCountVO.getUserId()).getGiveBalance());
            balanceCountVO.setRechargeBalance(balanceCountMap.get(balanceCountVO.getUserId()).getRechargeBalance());
            balanceCountVO.setWelfareBalance(balanceCountMap.get(balanceCountVO.getUserId()).getWelfareBalance());
        }
        return balanceCountVOS;
    }

    @Override
    public int findUserPageByBalanceCount(RechargeBalanceCountDTO rechargeBalanceCountDTO) {
        return baseMapper.findUserPageByBalanceCount(rechargeBalanceCountDTO, SecurityUtils.getLoginUser().getSourceType(), SecurityUtils.getLoginUser().getOrgId());
    }

    @Override
    public List<RechargeCardBillMstrQueryVO> getCardBillMstrInfoById(Long rechargeCardId) {
        RechargeCardBillMstrQueryDTO rechargeCardBillMstrQueryDTO = new RechargeCardBillMstrQueryDTO();
        rechargeCardBillMstrQueryDTO.setRechargeCardId(rechargeCardId);

        if (SourceType.STORE.getCode().equals(SecurityUtils.getLoginUser().getSourceType())) {
            rechargeCardBillMstrQueryDTO.setOrgId(SecurityUtils.getLoginUser().getOrgId());
            rechargeCardBillMstrQueryDTO.setSourceType(SourceType.STORE.getCode());
        }
        return baseMapper.getCardBillMstrInfoById(rechargeCardBillMstrQueryDTO);
    }

    @Override
    public List<RechargeCardBillMstrQueryVO> getBillMstrInfoList(BillMstrQueryDTO billMstrQueryDTO) {
        Long orgId = null;
        String sourceType = "";
        if (SourceType.STORE.getCode().equals(SecurityUtils.getLoginUser().getSourceType())) {
            orgId = SecurityUtils.getLoginUser().getOrgId();
            sourceType = SourceType.STORE.getCode();
        }
        return baseMapper.getBillMstrInfoList(billMstrQueryDTO, orgId, sourceType);
    }

    @Override
    public int countBillMstrInfoList(BillMstrQueryDTO billMstrQueryDTO) {
        Long orgId = null;
        String sourceType = "";
        if (SourceType.STORE.getCode().equals(SecurityUtils.getLoginUser().getSourceType())) {
            orgId = SecurityUtils.getLoginUser().getOrgId();
            sourceType = SourceType.STORE.getCode();
        }
        return baseMapper.countBillMstrInfoList(billMstrQueryDTO, orgId, sourceType);
    }

    /**
     * 查询密码充值卡管理
     *
     * @param id 密码充值卡管理主键
     * @return 密码充值卡管理
     */
    @Override
    public RechargePasswordCard selectRechargePasswordCardById(Long id) {
        return baseMapper.selectRechargePasswordCardById(id);
    }

    @Override
    public RechargePasswordCard selectRechargePasswordCardByOrderNo(String orderNo) {
        if (StringUtils.isNotEmpty(orderNo)) {
            return baseMapper.selectRechargePasswordCardByOrderNo(orderNo);
        }
        return null;
    }

    /**
     * 查询密码充值卡管理列表
     *
     * @param rechargePasswordCardQueryDTO 密码充值卡管理
     * @return 密码充值卡管理
     */
    @Override
    public List<RechargePasswordCardQueryVO> selectRechargePasswordCardList(RechargePasswordCardQueryDTO rechargePasswordCardQueryDTO) {
        List<RechargePasswordCardQueryVO> rechargePasswordCardQueryVOList = baseMapper.selectRechargePasswordCardList(rechargePasswordCardQueryDTO);
        for (RechargePasswordCardQueryVO rechargePasswordCardQueryVO : rechargePasswordCardQueryVOList) {
            rechargePasswordCardQueryVO.setRechargeStoreName("总部");
            if (rechargePasswordCardQueryVO.getRechargeStoreId() != null && rechargePasswordCardQueryVO.getRechargeStoreId() != 0) {
                SysStore sysStore = sysStoreService.selectSysStoreById(rechargePasswordCardQueryVO.getRechargeStoreId());
                rechargePasswordCardQueryVO.setRechargeStoreName(sysStore.getName());
            }
            rechargePasswordCardQueryVO.setUseBindStoreName("--");
            if (rechargePasswordCardQueryVO.getUseBindStoreId() != null && rechargePasswordCardQueryVO.getUseBindStoreId() != 0) {
                SysStore sysStore = sysStoreService.selectSysStoreById(rechargePasswordCardQueryVO.getUseBindStoreId());
                rechargePasswordCardQueryVO.setUseBindStoreName(sysStore.getName());
            }
        }
        return rechargePasswordCardQueryVOList;
    }

    /**
     * 新增密码充值卡管理
     *
     * @param rechargePasswordCard 密码充值卡管理
     * @return 结果
     */
    @Override
    public int insertRechargePasswordCard(RechargePasswordCard rechargePasswordCard) {
        rechargePasswordCard.setCreateTime(DateUtils.getNowDate());
        return baseMapper.insert(rechargePasswordCard);
    }

    /**
     * 修改密码充值卡管理
     *
     * @param rechargePasswordCard 密码充值卡管理
     * @return 结果
     */
    @Override
    public int updateRechargePasswordCard(RechargePasswordCard rechargePasswordCard) {
        rechargePasswordCard.setUpdateTime(DateUtils.getNowDate());
        return baseMapper.updateById(rechargePasswordCard);
    }

    /**
     * 批量删除密码充值卡管理
     *
     * @param ids 需要删除的密码充值卡管理主键
     * @return 结果
     */
    @Override
    public int deleteRechargePasswordCardByIds(Long[] ids) {
        return baseMapper.deleteRechargePasswordCardByIds(ids);
    }

    /**
     * 删除密码充值卡管理信息
     *
     * @param id 密码充值卡管理主键
     * @return 结果
     */
    @Override
    public int deleteRechargePasswordCardById(Long id) {
        return baseMapper.deleteRechargePasswordCardById(id);
    }

    /**
     * 导入未使用充值卡
     *
     * @param rechargePasswordImportDTOS 充值卡数据列表
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importData(List<RechargePasswordImportDTO> rechargePasswordImportDTOS, RechargeCardBatchRecord rechargeCardBatchRecord) {
        // 保存导入-未使用的充值卡
        this.buildRechargeCard(rechargePasswordImportDTOS, rechargeCardBatchRecord);
        return "导入成功";
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DirectChargingImportVO importDirectCharging(DirectChargingImportRequest request) {
        // 1. 校验数据
        validateImportData(request);

        try {
            // 2. 创建批次记录
            RechargeCardBatchRecord batchRecord = createBatchRecord(request);

            // 3. 获取门店和用户信息
            Map<String, SysStore> storeMap = getStoreMap(request.getImportList());
            Map<String, AppUser> userMap = getUserMap(request.getImportList());

            // 4. 构建并保存充值卡
            List<RechargePasswordCard> rechargeCards = buildAndSaveRechargeCards(
                    request.getImportList(),
                    batchRecord,
                    storeMap,
                    userMap
            );

            // 5. 创建订单和账单
            createOrdersAndBills(rechargeCards);

            // 6. 构建返回结果
            return DirectChargingImportVO.builder()
                    .batchNo(batchRecord.getBatchNo())
                    .totalCount(request.getImportList().size())
                    .successCount(rechargeCards.size())
                    .build();

        } catch (Exception e) {
            log.error("直充导入失败", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new ServiceException("导入失败:" + e.getMessage());
        }
    }

    /**
     * 校验导入数据
     */
    private void validateImportData(DirectChargingImportRequest request) {
        if (CollUtil.isEmpty(request.getImportList())) {
            throw new ServiceException("导入数据不能为空");
        }

        if (request.getImportList().size() > 2000) {
            throw new ServiceException("单次导入数量不能超过2000条");
        }

        if (StringUtils.isEmpty(request.getBatchName())) {
            throw new ServiceException("批次名称不能为空");
        }

        if (request.getExpireTime() != null && request.getExpireTime().before(new Date())) {
            throw new ServiceException("过期时间不能早于当前时间");
        }
    }

    /**
     * 创建批次记录
     */
    private RechargeCardBatchRecord createBatchRecord(DirectChargingImportRequest request) {
        RechargeCardBatchRecord batchRecord = new RechargeCardBatchRecord();
        batchRecord.setBatchNo(orderNoUtils.getOrderNo());
        batchRecord.setBatchName(request.getBatchName());
        batchRecord.setLastExpireTime(request.getExpireTime());
        batchRecord.setRemark(request.getRemark());
        batchRecord.setIsDirectRecharge(SysBoolType.YES.getCode());
        batchRecord.setCreateById(request.getOperatorId());
        batchRecord.setCreateBy(request.getOperatorName());
        batchRecord.setCreateTime(new Date());

        rechargeCardBatchRecordService.save(batchRecord);
        return batchRecord;
    }

    /**
     * 获取门店信息
     */
    private Map<String, SysStore> getStoreMap(List<DirectChargingImportDTO> importList) {
        Set<String> storeCodes = importList.stream()
                .map(DirectChargingImportDTO::getStoreCode)
                .filter(StringUtils::isNotEmpty)
                .collect(Collectors.toSet());

        if (CollUtil.isEmpty(storeCodes)) {
            return new HashMap<>();
        }

        return sysStoreService.list(new QueryWrapper<SysStore>().lambda()
                        .in(SysStore::getCode, storeCodes))
                .stream()
                .collect(Collectors.toMap(SysStore::getCode, Function.identity()));
    }

    /**
     * 获取用户信息
     */
    private Map<String, AppUser> getUserMap(List<DirectChargingImportDTO> importList) {
        Set<String> phones = importList.stream()
                .map(DirectChargingImportDTO::getAppUserPhoneNumber)
                .collect(Collectors.toSet());

        Map<String, AppUser> userMap = appUserService.list(new QueryWrapper<AppUser>().lambda()
                        .in(AppUser::getPhoneNumber, phones))
                .stream()
                .collect(Collectors.toMap(AppUser::getPhoneNumber, Function.identity()));

        if (userMap.size() != phones.size()) {
            List<String> notExistPhones = phones.stream()
                    .filter(phone -> !userMap.containsKey(phone))
                    .collect(Collectors.toList());
            throw new ServiceException("以下手机号未注册:" + String.join(",", notExistPhones));
        }

        return userMap;
    }

    /**
     * 构建并保存充值卡
     */
    private List<RechargePasswordCard> buildAndSaveRechargeCards(
            List<DirectChargingImportDTO> importList,
            RechargeCardBatchRecord batchRecord,
            Map<String, SysStore> storeMap,
            Map<String, AppUser> userMap) {

        List<RechargePasswordCard> rechargeCards = importList.stream()
                .map(importDTO -> buildRechargeCard(importDTO, batchRecord, storeMap, userMap))
                .collect(Collectors.toList());

        saveBatch(rechargeCards);
        return rechargeCards;
    }

    /**
     * 构建充值卡
     */
    private RechargePasswordCard buildRechargeCard(
            DirectChargingImportDTO importDTO,
            RechargeCardBatchRecord batchRecord,
            Map<String, SysStore> storeMap,
            Map<String, AppUser> userMap) {

        RechargePasswordCard card = new RechargePasswordCard();

        // 设置基本信息
        card.setBatchNo(batchRecord.getBatchNo());
        card.setCardNo(orderNoUtils.getOrderNo());
        card.setPassword(Utils.getPassWordOne(8));
        card.setCreateType(RechargeCreateType.IMPORT.getCode());

        // 设置金额
        card.setRechargeAmount(importDTO.getRechargeAmount());
        card.setGiveAmount(BigDecimal.ZERO);
        card.setGivePointAmount(0);
        card.setRechargeBalance(card.getRechargeAmount());
        card.setGiveBalance(card.getGiveAmount());

        // 设置状态
        card.setDelFlag(DeleteStatus.OK.getCode());
        card.setRechargeStatus(RechargeStatusType.HAS_USE.getCode());
        card.setRechargeTime(new Date());

        // 设置用户
        AppUser user = userMap.get(importDTO.getAppUserPhoneNumber());
        card.setRechargeUserId(user.getId());

        // 设置权限
        card.setIsSupportLife(SysBoolType.YES.getCode());
        card.setIsSupportGoods(SysBoolType.YES.getCode());
        card.setIsSupportCloth(SysBoolType.YES.getCode());
        card.setIsSupportCar(SysBoolType.YES.getCode());

        // 设置创建信息
        card.setCreateById(batchRecord.getCreateById());
        card.setCreateBy(batchRecord.getCreateBy());
        card.setCreateTime(new Date());

        // 设置门店
        if (StringUtils.isNotEmpty(importDTO.getStoreCode())) {
            SysStore store = storeMap.get(importDTO.getStoreCode());
            if (store != null) {
                card.setRechargeStoreId(store.getId());
                card.setUseBindStoreId(store.getId());
            }
        }

        return card;
    }

    /**
     * 创建订单和账单
     */
    private void createOrdersAndBills(List<RechargePasswordCard> rechargeCards) {
        for (RechargePasswordCard card : rechargeCards) {
            try {
                // 创建充值订单
                OrderRecharge orderRecharge = orderRechargeService.buildOrderRechargeByCardPassword(
                        card,
                        OrderRechargeCreateDTO.buildDirectChargingCardByOrder(card.getRechargeUserId())
                );

                // 创建账单记录
                appUserBillMstrService.consumeRecord(
                        ConsumeOrderDTO.buildOrderRechargeData(orderRecharge)
                );

                // 更新充值卡订单号
                card.setOrderNo(orderRecharge.getOrderNo());
                updateById(card);

                log.info("创建订单成功, 充值卡号:{}, 订单号:{}",
                        card.getCardNo(), orderRecharge.getOrderNo());

            } catch (Exception e) {
                log.error("创建订单失败, 充值卡号:{}", card.getCardNo(), e);
                throw new ServiceException("创建订单失败:" + e.getMessage());
            }
        }
    }


    /**
     * 保存导入-未使用的充值卡
     *
     * @param rechargePasswordImportDTOS
     * @param rechargeCardBatchRecord
     */
    public void buildRechargeCard(List<RechargePasswordImportDTO> rechargePasswordImportDTOS, RechargeCardBatchRecord rechargeCardBatchRecord) {
        Map<String, SysStore> storeMap = sysStoreService.list(new QueryWrapper<SysStore>().lambda()
                        .in(SysStore::getCode, rechargePasswordImportDTOS.stream().filter(item -> StringUtils.isNotEmpty(item.getStoreCode()))
                                .map(RechargePasswordImportDTO::getStoreCode).collect(Collectors.toSet()))).stream()
                .collect(Collectors.toMap(SysStore::getCode, SysStore -> SysStore));
        List<RechargePasswordCard> rechargePasswordCards = new ArrayList<>();
        for (RechargePasswordImportDTO rechargePasswordImportDTO : rechargePasswordImportDTOS) {
            RechargePasswordCard rechargePasswordCard = new RechargePasswordCard();
            rechargePasswordCard.setBatchNo(rechargeCardBatchRecord.getBatchNo());
            rechargePasswordCard.setCardNo(rechargePasswordImportDTO.getCardNo());
            rechargePasswordCard.setPassword(rechargePasswordImportDTO.getPassword());
            rechargePasswordCard.setCreateType(RechargeCreateType.IMPORT.getCode());
            rechargePasswordCard.setRechargeAmount(rechargePasswordImportDTO.getRechargeAmount());
            rechargePasswordCard.setGiveAmount(rechargePasswordImportDTO.getGiveAmount());
            rechargePasswordCard.setGivePointAmount(rechargePasswordImportDTO.getGivePointAmount());
            rechargePasswordCard.setRechargeBalance(rechargePasswordCard.getRechargeAmount());
            rechargePasswordCard.setGiveBalance(rechargePasswordCard.getGiveAmount());
            rechargePasswordCard.setDelFlag(DeleteStatus.OK.getCode());
            rechargePasswordCard.setRechargeStatus(RechargeStatusType.NOT_UES.getCode());
            rechargePasswordCard.setRechargeStoreId(storeMap.get(rechargePasswordImportDTO.getStoreCode()).getId());
            rechargePasswordCard.setExpireTime(rechargeCardBatchRecord.getLastExpireTime());
            rechargePasswordCard.setCreateById(SecurityUtils.getUserId());
            rechargePasswordCard.setCreateBy(SecurityUtils.getUsername());
            rechargePasswordCard.setCreateTime(DateUtils.getNowDate());
            rechargePasswordCard.setIsSupportLife(SysBoolType.YES.getCode());
            rechargePasswordCard.setIsSupportGoods(SysBoolType.YES.getCode());
            rechargePasswordCard.setIsSupportCloth(SysBoolType.YES.getCode());
            rechargePasswordCard.setIsSupportCar(SysBoolType.YES.getCode());
            rechargePasswordCards.add(rechargePasswordCard);
        }
        saveBatch(rechargePasswordCards);
    }

    /**
     * 按客户获取充值卡信息
     */
    @Override
    public List<WeAppCardsInfoVO> getPasswordCardsInfoByAppUserId(WeAppCardRecordByUserDTO weAppCardRecordByUserDTO) {
        weAppCardRecordByUserDTO.setAppUserId(AuthHolder.userId());
        return baseMapper.getPasswordCardsInfoByAppUserId(weAppCardRecordByUserDTO);
    }

    /**
     * 按充值卡查消费记录
     */
    @Override
    public WeAppCardsUseRecordsVO getUseRecordsByCardId(WeAppCardRecordByCardDTO weAppCardRecordByCardDTO) {
        if (StrUtil.isEmpty(String.valueOf(weAppCardRecordByCardDTO.getRechargePasswordCardId()))) {
            throw new GlobalException("充值卡id为空");
        }
        WeAppCardsUseRecordsVO recordInfo = baseMapper.getUseRecordsByCardId(weAppCardRecordByCardDTO);
        recordInfo.setUserBillMstrList(appUserBillMstrService.list(new QueryWrapper<AppUserBillMstr>().lambda()
                .eq(AppUserBillMstr::getRechargeCardNo, recordInfo.getCardNo())
                .eq(AppUserBillMstr::getAppUserId, weAppCardRecordByCardDTO.getAppUserId())
                .orderByDesc(AppUserBillMstr::getCreateTime)
                .last("limit " + weAppCardRecordByCardDTO.getStartRow() + "," + weAppCardRecordByCardDTO.getPageSize())));
        return recordInfo;
    }

    @Override
    public void orderPayByBalance(RechargeCardPayDTO rechargeCardPayDTO) throws ServiceException {
        List<RechargePasswordCard> cardList = baseMapper.selectRechargePasswordCardListByAppUserIdAndBuyGoodsType(rechargeCardPayDTO.getAppUserId(), rechargeCardPayDTO.getBuyGoodsType());
        if (CollUtil.isEmpty(cardList)) {
            throw new ServiceException("该用户没有可用的充值卡");
        }
        BigDecimal totalRechargeBalance = cardList.stream().map(RechargePasswordCard::getRechargeBalance).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal totalGiveBalance = cardList.stream().map(RechargePasswordCard::getGiveBalance).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal totalWelfareBalance = cardList.stream().map(RechargePasswordCard::getWelfareBalance).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal totalAmount = CurrencyUtil.add(totalRechargeBalance, totalGiveBalance, totalWelfareBalance);
        if (totalAmount.compareTo(rechargeCardPayDTO.getPayAmount()) < 0) {
            throw new ServiceException("该用户余额不足：" + totalAmount);
        }
        Map<Long, RechargePasswordCard> cardMap = cardList.stream().collect(Collectors.toMap(RechargePasswordCard::getId, Function.identity()));
        BigDecimal remainPayAmount = rechargeCardPayDTO.getPayAmount();
        List<RechargePasswordCard> payCardList = new ArrayList<>();
        for (RechargePasswordCard rechargePasswordCard : cardList) {
            //优先扣款账户余额，如果余额不足的情况，在扣款赠送金额，最后扣款福利金额
            RechargePasswordCard updateRechargePasswordCard = new RechargePasswordCard();
            updateRechargePasswordCard.setId(rechargePasswordCard.getId());
            updateRechargePasswordCard.setCardNo(rechargePasswordCard.getCardNo());
            updateRechargePasswordCard.setRechargeBalance(BigDecimal.ZERO);
            updateRechargePasswordCard.setGiveBalance(BigDecimal.ZERO);
            updateRechargePasswordCard.setWelfareBalance(BigDecimal.ZERO);
            //判断余额是否充足，查找每张卡的扣款金额
            if (rechargePasswordCard.getRechargeBalance().compareTo(BigDecimal.ZERO) > 0) {
                if (rechargePasswordCard.getRechargeBalance().compareTo(remainPayAmount) >= 0) {
                    updateRechargePasswordCard.setRechargeBalance(remainPayAmount);
                } else {
                    updateRechargePasswordCard.setRechargeBalance(rechargePasswordCard.getRechargeBalance());
                }
                remainPayAmount = CurrencyUtil.sub(remainPayAmount, updateRechargePasswordCard.getRechargeBalance());
            }
            if (remainPayAmount.compareTo(BigDecimal.ZERO) > 0 && rechargePasswordCard.getGiveBalance().compareTo(BigDecimal.ZERO) > 0) {
                if (rechargePasswordCard.getGiveBalance().compareTo(remainPayAmount) >= 0) {
                    updateRechargePasswordCard.setGiveBalance(remainPayAmount);
                } else {
                    updateRechargePasswordCard.setGiveBalance(rechargePasswordCard.getGiveBalance());
                }
                remainPayAmount = CurrencyUtil.sub(remainPayAmount, updateRechargePasswordCard.getGiveBalance());
            }
            if (remainPayAmount.compareTo(BigDecimal.ZERO) > 0 && rechargePasswordCard.getWelfareBalance().compareTo(BigDecimal.ZERO) > 0) {
                if (rechargePasswordCard.getWelfareBalance().compareTo(remainPayAmount) >= 0) {
                    updateRechargePasswordCard.setWelfareBalance(remainPayAmount);
                } else {
                    updateRechargePasswordCard.setWelfareBalance(rechargePasswordCard.getWelfareBalance());
                }
                remainPayAmount = CurrencyUtil.sub(remainPayAmount, updateRechargePasswordCard.getWelfareBalance());
            }
            if (updateRechargePasswordCard.getRechargeBalance().compareTo(BigDecimal.ZERO) > 0 || updateRechargePasswordCard.getGiveBalance().compareTo(BigDecimal.ZERO) > 0 || updateRechargePasswordCard.getWelfareBalance().compareTo(BigDecimal.ZERO) > 0) {
                payCardList.add(updateRechargePasswordCard);
            }
            if (remainPayAmount.compareTo(BigDecimal.ZERO) <= 0) {
                break;
            }
        }
        log.info("订单{}，会员卡消费扣款成功，每张卡扣款记录：【{}】", rechargeCardPayDTO.getOrderNo(), JSONUtil.toJsonStr(payCardList));
        // 更新余额
        for (RechargePasswordCard updateRechargePasswordCard : payCardList) {
            RechargePasswordCard rechargePasswordCard = cardMap.get(updateRechargePasswordCard.getId());
            rechargePasswordCard.setRechargeBalance(CurrencyUtil.sub(rechargePasswordCard.getRechargeBalance(), updateRechargePasswordCard.getRechargeBalance()));
            rechargePasswordCard.setGiveBalance(CurrencyUtil.sub(rechargePasswordCard.getGiveBalance(), updateRechargePasswordCard.getGiveBalance()));
            rechargePasswordCard.setWelfareBalance(CurrencyUtil.sub(rechargePasswordCard.getWelfareBalance(), updateRechargePasswordCard.getWelfareBalance()));
            rechargePasswordCard.buildUpdateData();
            if (rechargePasswordCard.getRechargeBalance().compareTo(BigDecimal.ZERO) == 0) {
                //如果卡余额为0，则设置赠送余额激活时间，过期时间是1年
                rechargePasswordCard.setGiveActiveTime(DateUtils.getNowDate());
                rechargePasswordCard.setGiveExpiredTime(DateUtils.addMonths(DateUtils.getNowDate(), 12));
            }
            baseMapper.updateById(rechargePasswordCard);
            //保存日志
            BillMstrOrderDTO billMstrOrderDTO = new BillMstrOrderDTO();
            billMstrOrderDTO.setAppUserId(rechargeCardPayDTO.getAppUserId());
            billMstrOrderDTO.setOrgId(rechargeCardPayDTO.getOrgId());
            billMstrOrderDTO.setSourceType(rechargeCardPayDTO.getSourceType());
            billMstrOrderDTO.setOrderId(rechargeCardPayDTO.getOrderId());
            billMstrOrderDTO.setUseBindStoreId(rechargePasswordCard.getUseBindStoreId());
            billMstrOrderDTO.setOrderNo(rechargeCardPayDTO.getOrderNo());
            billMstrOrderDTO.setOrderType(rechargeCardPayDTO.getBuyGoodsType());
            billMstrOrderDTO.setRechargePayAmount(updateRechargePasswordCard.getRechargeBalance());
            billMstrOrderDTO.setWelfarePayAmount(updateRechargePasswordCard.getWelfareBalance());
            billMstrOrderDTO.setGivePayAmount(updateRechargePasswordCard.getGiveBalance());
            billMstrOrderDTO.setRechargeCardNo(rechargePasswordCard.getCardNo());
            BigDecimal totalPayAmount = CurrencyUtil.add(updateRechargePasswordCard.getRechargeBalance(), updateRechargePasswordCard.getGiveBalance(), updateRechargePasswordCard.getWelfareBalance());
            billMstrOrderDTO.setPayTotalAmount(totalPayAmount);
            billMstrOrderDTO.setRemark("充值卡：" + rechargePasswordCard.getCardNo() + "，消费" + totalPayAmount + "元");
            billMstrOrderService.saveBillMstrOrder(billMstrOrderDTO);
            log.info("订单{}，会员卡 {} 扣款成功，扣款日志：【{}】", rechargeCardPayDTO.getOrderNo(), billMstrOrderDTO.getRechargeCardNo(), billMstrOrderDTO.getRemark());
        }
    }

    @Override
    public RechargePasswordCard selectRechargePasswordCardBySn(String cardSn) {
        return baseMapper.selectRechargePasswordCardBySn(cardSn);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean orderRefundByBalance(String orderSn, BigDecimal refundAmount) {
        List<AppUserBillMstr> consumeBillMstrs = appUserBillMstrService.list(new QueryWrapper<AppUserBillMstr>().lambda()
                .eq(AppUserBillMstr::getOrderNo, orderSn)
                .eq(AppUserBillMstr::getBillType, "0")
        );
        BigDecimal remainRefundAmount = refundAmount;
        for (AppUserBillMstr consumeBillMstr : consumeBillMstrs) {
            //原充值卡退款
            RechargePasswordCard rechargePasswordCard = selectRechargePasswordCardBySn(consumeBillMstr.getRechargeCardNo());
            if (rechargePasswordCard == null) {
                throw new ServiceException("充值卡不存在");
            }
            if (rechargePasswordCard.getRechargeStatus().equals(RechargeStatusType.REFUND.getCode())) {
                throw new ServiceException("该充值卡已退款，无法撤回");
            }
            BigDecimal giveRefundAmount = BigDecimal.ZERO;
            BigDecimal welfareRefundAmount = BigDecimal.ZERO;
            BigDecimal balanceRefundAmount = BigDecimal.ZERO;
            if (remainRefundAmount.compareTo(consumeBillMstr.getGivePayAmount()) > 0) {
                giveRefundAmount = consumeBillMstr.getGivePayAmount();
            } else {
                giveRefundAmount = remainRefundAmount;
            }
            remainRefundAmount = CurrencyUtil.sub(remainRefundAmount, giveRefundAmount);
            if (remainRefundAmount.compareTo(consumeBillMstr.getWelfarePayAmount()) > 0) {
                welfareRefundAmount = consumeBillMstr.getWelfarePayAmount();
            } else {
                welfareRefundAmount = remainRefundAmount;
            }
            remainRefundAmount = CurrencyUtil.sub(remainRefundAmount, welfareRefundAmount);
            if (remainRefundAmount.compareTo(consumeBillMstr.getRechargePayAmount()) > 0) {
                balanceRefundAmount = consumeBillMstr.getRechargePayAmount();
            } else {
                balanceRefundAmount = remainRefundAmount;
            }
            remainRefundAmount = CurrencyUtil.sub(remainRefundAmount, balanceRefundAmount);
            rechargePasswordCard.setRechargeBalance(CurrencyUtil.add(rechargePasswordCard.getRechargeBalance(), balanceRefundAmount));
            rechargePasswordCard.setGiveBalance(CurrencyUtil.add(rechargePasswordCard.getGiveBalance(), giveRefundAmount));
            rechargePasswordCard.setWelfareBalance(CurrencyUtil.add(rechargePasswordCard.getWelfareBalance(), welfareRefundAmount));
            rechargePasswordCard.setRechargeStatus(RechargeStatusType.HAS_USE.getCode());
            baseMapper.updateById(rechargePasswordCard);
            //新增一个充值记录
            //保存日志
            consumeBillMstr.setRechargePayAmount(balanceRefundAmount);
            consumeBillMstr.setWelfarePayAmount(welfareRefundAmount);
            consumeBillMstr.setGivePayAmount(giveRefundAmount);
            consumeBillMstr.setPayTotalAmount(CurrencyUtil.add(balanceRefundAmount, giveRefundAmount, welfareRefundAmount));

            BillMstrOrderDTO billMstrOrderDTO = new BillMstrOrderDTO();
            BeanUtils.copyProperties(consumeBillMstr, billMstrOrderDTO);
            billMstrOrderDTO.setOrgId(consumeBillMstr.getOrgId());
            billMstrOrderDTO.setOrderId(consumeBillMstr.getOrderId());
            billMstrOrderDTO.setSourceType(consumeBillMstr.getSourceType());
            billMstrOrderDTO.setUseBindStoreId(rechargePasswordCard.getUseBindStoreId());
            billMstrOrderDTO.setRechargeCardNo(rechargePasswordCard.getCardNo());
            billMstrOrderDTO.setRemark("充值卡：" + rechargePasswordCard.getCardNo() + "，订单退款，退还" + consumeBillMstr.getPayTotalAmount() + "元");
            billMstrOrderService.saveRefundBillMstrOrder(billMstrOrderDTO);
            log.info("订单{}，会员卡 {} 退款成功，扣款日志：【{}】", consumeBillMstr.getOrderNo(), billMstrOrderDTO.getRechargeCardNo(), JSONUtil.toJsonStr(billMstrOrderDTO));
        }
        return true;
    }

    @Override
    public TableDataInfo<StoreCardStatisticsVO> getStoreCardStatisticsPage(Long storeId, Date beginTime, Date endTime, int pageNum, int pageSize) {
        int startRow = (pageNum - 1) * pageSize;
        // 获取分页数据
        List<StoreCardStatisticsVO> list = baseMapper.selectStoreCardStatisticsPage(storeId, beginTime, endTime, startRow, pageSize);

        // 获取总门店数
        Long total = sysStoreService.count(new QueryWrapper<SysStore>().lambda()
                .gt(SysStore::getId, 0)
                .eq(SysStore::getDelFlag, DeleteStatus.OK.getCode()));

        return new TableDataInfo<>(list, total.intValue());
    }

    @Override
    public List<StoreCardStatisticsVO> getStoreCardStatisticsExport(Long storeId, Date beginTime, Date endTime) {
        // 不分页，导出全部
        return baseMapper.selectStoreCardStatisticsPage(storeId, beginTime, endTime, 0, Integer.MAX_VALUE);
    }
}
