package com.yiqi.recharge.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
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.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 java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
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 ISysSettlementRateService settlementRateService;
    @Autowired
    private IAppUserBillMstrService billMstrOrderService;

    @Override
    public void refundBalance(ConsumeOrderDTO consumeOrderDTO) {
        List<AppUserBillMstr> consumeBillMstrs = appUserBillMstrService.list(new QueryWrapper<AppUserBillMstr>().lambda()
                .eq(AppUserBillMstr::getOrderNo, consumeOrderDTO.getOrderNo())
                .eq(AppUserBillMstr::getIsRefund, SysBoolType.NO.getCode())
                .eq(AppUserBillMstr::getPayType, PayType.BALANCE.getCode()));
        //修改消费记录为已被退款状态
        appUserBillMstrService.update(new UpdateWrapper<AppUserBillMstr>().lambda()
                .eq(AppUserBillMstr::getOrderNo, consumeOrderDTO.getOrderNo())
                .eq(AppUserBillMstr::getPayTotalAmount, PayType.BALANCE.getCode())
                .eq(AppUserBillMstr::getIsRefund, SysBoolType.NO.getCode())
                .set(AppUserBillMstr::getHasRefund, SysBoolType.YES.getCode()));
        if (consumeBillMstrs.size() == 0) {
            return;
        }

        Map<Long, RechargePasswordCard> rechargePasswordCardMap = list(new QueryWrapper<RechargePasswordCard>().lambda()
                .in(RechargePasswordCard::getId,
                        consumeBillMstrs.stream()
                                .map(AppUserBillMstr::getRechargeCardId)
                                .collect(Collectors.toSet()))).stream()
                .collect(Collectors.toMap(RechargePasswordCard::getId, RechargePasswordCard -> RechargePasswordCard));

        List<AppUserBillMstr> appUserBillMstrs = new ArrayList<>();
        for (AppUserBillMstr consumeBillMstr : consumeBillMstrs) {
            if (OrderType.recharge.getCode().equals(consumeBillMstr.getOrderType())) {
                appUserBillMstrs.add(
                        buildBillMstr(consumeOrderDTO, consumeBillMstr, rechargePasswordCardMap.get(consumeBillMstr.getRechargeCardId())
                                , consumeBillMstr.getRechargePayAmount()
                                , consumeBillMstr.getGivePayAmount()
                                , consumeBillMstr.getWelfarePayAmount()));
            } else {
                appUserBillMstrs.add(
                        buildBillMstr(consumeOrderDTO, consumeBillMstr, rechargePasswordCardMap.get(consumeBillMstr.getRechargeCardId())
                                , consumeBillMstr.getRechargePayAmount().multiply(new BigDecimal(-1))
                                , consumeBillMstr.getGivePayAmount().multiply(new BigDecimal(-1))
                                , consumeBillMstr.getWelfarePayAmount().multiply(new BigDecimal(-1))));
            }
        }
        appUserBillMstrService.saveBatch(appUserBillMstrs);
    }

    @Override
    public void deductBalance(ConsumeOrderDTO consumeOrderDTO) {
        LambdaQueryWrapper<RechargePasswordCard> queryWrapper = new QueryWrapper<RechargePasswordCard>().lambda()
                .eq(RechargePasswordCard::getRechargeUserId, consumeOrderDTO.getAppUserId())
                .and(wrapper -> wrapper.gt(RechargePasswordCard::getRechargeBalance, BigDecimal.ZERO)
                        .or()
                        .gt(RechargePasswordCard::getGiveBalance, BigDecimal.ZERO))
                .and(wrapper -> wrapper.ge(RechargePasswordCard::getExpireTime, DateUtils.getNowDate(DateUtils.YYYY_MM_DD))
                        .or().isNull(RechargePasswordCard::getExpireTime))
                .orderByDesc(RechargePasswordCard::getUseLevel)
                .orderByAsc(RechargePasswordCard::getRechargeTime);
        switch (EnumUtils.getEnumByType(consumeOrderDTO.getOrderType(), OrderType.class)) {
            case cloth:
            case delivery: {
                queryWrapper.eq(RechargePasswordCard::getIsSupportCloth, SysBoolType.YES.getCode());
                break;
            }
            case goods: {
                queryWrapper.eq(RechargePasswordCard::getIsSupportGoods, SysBoolType.YES.getCode());
                break;
            }
            case car: {
                queryWrapper.eq(RechargePasswordCard::getIsSupportCar, SysBoolType.YES.getCode());
                break;
            }
            case life: {
                queryWrapper.eq(RechargePasswordCard::getIsSupportLife, SysBoolType.YES.getCode());
                break;
            }
            default: {
                throw new ServiceException("余额付款订单类型不正确");
            }
        }
        List<RechargePasswordCard> list = list(queryWrapper);
        BigDecimal amount = new BigDecimal(consumeOrderDTO.getAmount().doubleValue());
        List<RechargePasswordCard> updateList = new ArrayList<>();//待修改余额的充值卡
        List<AppUserBillMstr> appUserBillMstrs = new ArrayList<>();
        for (RechargePasswordCard rechargePasswordCard : list) {
            updateList.add(rechargePasswordCard);
            rechargePasswordCard.setRechargeStatus(RechargeStatusType.HAS_USE.getCode());

            BigDecimal useAmount = BigDecimal.ZERO;//本卡使用金额，如果涉及到异店消费，使用本卡使用金额计算
            BigDecimal rechargeAmount = BigDecimal.ZERO, giveAmount = BigDecimal.ZERO, welfareAmount = BigDecimal.ZERO;
            if (rechargePasswordCard.getRechargeBalance() != null
                    && rechargePasswordCard.getRechargeBalance().doubleValue() > 0) {
                //如果充值余额比需要支付的金额大
                if (rechargePasswordCard.getRechargeBalance().doubleValue() >= amount.doubleValue()) {
                    rechargePasswordCard.setRechargeBalance(rechargePasswordCard.getRechargeBalance().subtract(amount));
                    rechargeAmount = rechargeAmount.add(amount);
                    useAmount = useAmount.add(amount);
                    amount = BigDecimal.ZERO;
                    //如果现金余额已用完，则激活赠送余额到期时间
                    if (rechargePasswordCard.getRechargeBalance().doubleValue() == 0) {
                        rechargePasswordCard.setExpireTime(DateUtils.addYears(DateUtils.getNowDate(), 1));
                    }
                } else {
                    amount = amount.subtract(rechargePasswordCard.getRechargeBalance());
                    rechargeAmount = rechargeAmount.add(rechargePasswordCard.getRechargeBalance());
                    rechargePasswordCard.setRechargeBalance(BigDecimal.ZERO);
                }
            }

            //扣款完成
            if (amount.doubleValue() == 0) {
                updateList.add(rechargePasswordCard);
                appUserBillMstrs.add(buildBillMstr(consumeOrderDTO, rechargePasswordCard, rechargeAmount, giveAmount, welfareAmount));
                break;
            }

            //使用赠送余额
            if (rechargePasswordCard.getGiveBalance() != null
                    && rechargePasswordCard.getGiveBalance().doubleValue() > 0) {
                if (rechargePasswordCard.getGiveBalance().doubleValue() >= amount.doubleValue()) {
                    rechargePasswordCard.setGiveBalance(rechargePasswordCard.getGiveBalance().subtract(amount));
                    giveAmount = giveAmount.add(amount);
                    amount = BigDecimal.ZERO;
                } else {
                    amount = amount.subtract(rechargePasswordCard.getGiveBalance());
                    giveAmount = giveAmount.add(rechargePasswordCard.getGiveBalance());
                    rechargePasswordCard.setGiveBalance(BigDecimal.ZERO);
                }
            }

            //扣款完成
            if (amount.doubleValue() == 0) {
                updateList.add(rechargePasswordCard);
                appUserBillMstrs.add(buildBillMstr(consumeOrderDTO, rechargePasswordCard, rechargeAmount, giveAmount, welfareAmount));
                break;
            }

//            if (rechargePasswordCard.getWelfareBalance() != null
//                    && rechargePasswordCard.getWelfareBalance().doubleValue() > 0) {
//                if (rechargePasswordCard.getWelfareBalance().doubleValue() >= amount.doubleValue()) {
//                    rechargePasswordCard.setWelfareBalance(rechargePasswordCard.getWelfareBalance().subtract(amount));
//                    welfareAmount = welfareAmount.add(amount);
//                    amount = BigDecimal.ZERO;
//                } else {
//                    amount = amount.subtract(rechargePasswordCard.getWelfareBalance());
//                    welfareAmount = welfareAmount.add(rechargePasswordCard.getWelfareBalance());
//                    rechargePasswordCard.setWelfareBalance(BigDecimal.ZERO);
//                }
//            }
            updateList.add(rechargePasswordCard);
            appUserBillMstrs.add(buildBillMstr(consumeOrderDTO, rechargePasswordCard, rechargeAmount, giveAmount, welfareAmount));
            if (amount.doubleValue() == 0) {//扣款完成
                break;
            }
        }

        /**
         * 全部修改完成，如果还有金额没有扣完，则说明余额不足
         */
        if (amount.doubleValue() > 0) {
            throw new ServiceException("余额不足");
        }
        updateBatchById(updateList);
        appUserBillMstrService.saveBatch(appUserBillMstrs);
    }

    /**
     * 余额退款专用
     */
    private AppUserBillMstr buildBillMstr(ConsumeOrderDTO consumeOrderDTO, AppUserBillMstr oldBillMstr
            , RechargePasswordCard rechargePasswordCard
            , BigDecimal rechargeAmount, BigDecimal giveAmount, BigDecimal welfareAmount) {
        AppUserBillMstr appUserBillMstr = buildBillMstr(consumeOrderDTO, rechargePasswordCard, rechargeAmount, giveAmount, welfareAmount);
        appUserBillMstr.setIsOtherStore(oldBillMstr.getIsOtherStore());
        appUserBillMstr.setOtherStoreAmount(oldBillMstr.getOtherStoreAmount());
        appUserBillMstr.setOtherStoreRate(oldBillMstr.getOtherStoreRate());
        appUserBillMstr.setOtherStoreOrgId(oldBillMstr.getOtherStoreOrgId());
        return appUserBillMstr;
    }


    /**
     * 消费日志
     *
     * @param consumeOrderDTO      消费信息
     * @param rechargePasswordCard 充值卡
     * @param rechargeAmount       充值余额支付金额
     * @param giveAmount           赠送余额支付金额
     * @param welfareAmount        福利金余额支付金额
     * @return
     */
    @Override
    public AppUserBillMstr buildBillMstr(ConsumeOrderDTO consumeOrderDTO, RechargePasswordCard rechargePasswordCard
            , BigDecimal rechargeAmount, BigDecimal giveAmount, BigDecimal welfareAmount) {
        AppUserBillMstr appUserBillMstr = new AppUserBillMstr();
        appUserBillMstr.buildCreateData();
        appUserBillMstr.setAppUserId(consumeOrderDTO.getAppUserId());
        if (rechargePasswordCard != null) {
            appUserBillMstr.setBatchNo(rechargePasswordCard.getBatchNo());
        }
        if ((SysBoolType.NO.getCode().equals(consumeOrderDTO.getIsRefund())
                && !OrderType.recharge.getCode().equals(consumeOrderDTO.getOrderType()))
                || (SysBoolType.YES.getCode().equals(consumeOrderDTO.getIsRefund())
                && OrderType.recharge.getCode().equals(consumeOrderDTO.getOrderType()))) {
            appUserBillMstr.setBillType(OrderBillType.pay.getCode());
            appUserBillMstr.setPayTotalAmount((rechargeAmount.add(giveAmount).add(welfareAmount)).multiply(new BigDecimal(-1)));
            appUserBillMstr.setCashPayAmount(BigDecimal.ZERO);
            appUserBillMstr.setRechargePayAmount(rechargeAmount.multiply(new BigDecimal(-1)));
            appUserBillMstr.setGivePayAmount(giveAmount.multiply(new BigDecimal(-1)));
            appUserBillMstr.setWelfarePayAmount(welfareAmount.multiply(new BigDecimal(-1)));
        } else {
            appUserBillMstr.setBillType(OrderBillType.recharge.getCode());
            appUserBillMstr.setPayTotalAmount(rechargeAmount.add(giveAmount).add(welfareAmount));
            appUserBillMstr.setCashPayAmount(BigDecimal.ZERO);
            appUserBillMstr.setRechargePayAmount(rechargeAmount);
            appUserBillMstr.setGivePayAmount(giveAmount);
            appUserBillMstr.setWelfarePayAmount(welfareAmount);
        }

        switch (EnumUtils.getEnumByType(consumeOrderDTO.getOrderType(), OrderType.class)) {
            case cloth: {
                appUserBillMstr.setUsePoint(consumeOrderDTO.getPointAmount());
                appUserBillMstr.setReceivePoint(0);
                appUserBillMstr.setTitle("洗衣订单");
                break;
            }
            case goods: {
                appUserBillMstr.setUsePoint(consumeOrderDTO.getPointAmount());
                appUserBillMstr.setReceivePoint(0);
                appUserBillMstr.setTitle("商品订单");
                break;
            }
            case life: {
                appUserBillMstr.setUsePoint(consumeOrderDTO.getPointAmount());
                appUserBillMstr.setReceivePoint(0);
                appUserBillMstr.setTitle("生活服务");
                break;
            }
            case car: {
                appUserBillMstr.setUsePoint(consumeOrderDTO.getPointAmount());
                appUserBillMstr.setReceivePoint(0);
                appUserBillMstr.setTitle("汽车美容");
                break;
            }
            case recharge: {
                appUserBillMstr.setReceivePoint(consumeOrderDTO.getPointAmount());
                appUserBillMstr.setUsePoint(0);
                appUserBillMstr.setTitle("充值");
                break;
            }
        }
        appUserBillMstr.setIsRefund(consumeOrderDTO.getIsRefund());
        appUserBillMstr.setOrderId(consumeOrderDTO.getOrderId());
        appUserBillMstr.setOrderNo(consumeOrderDTO.getOrderNo());
        appUserBillMstr.setOrderType(consumeOrderDTO.getOrderType());
        appUserBillMstr.setOrgId(consumeOrderDTO.getStoreId());
        appUserBillMstr.setPayType(consumeOrderDTO.getPayType());
        appUserBillMstr.setHasRefund(SysBoolType.NO.getCode());
        if (rechargePasswordCard != null) {
            appUserBillMstr.setRechargeCardId(rechargePasswordCard.getId());
        }

        //这里判断一下是否为异店消费（非充值订单）
//        if(SysBoolType.NO.getCode().equals(consumeOrderDTO.getIsRefund())
//                && !OrderType.recharge.getCode().equals(consumeOrderDTO.getOrderType())
//        && PayType.BALANCE.getCode().equals(consumeOrderDTO.getPayType()) //余额支付、非退款、非充值订单
//                && consumeOrderDTO.getOrgId().longValue() != rechargePasswordCard.getRechargeOrgId().longValue()){//是其他店的卡消费，触发异店结算
//            SysSettlementRate sysSettlementRate = settlementRateService.
//                    getOne(new QueryWrapper<SysSettlementRate>().lambda()
//                            .eq(SysSettlementRate::getOrgId, rechargePasswordCard.getRechargeOrgId())
//                            .eq(SysSettlementRate::getSourceType,SourceType.STORE.getCode()));
//            if(sysSettlementRate == null){
//                appUserBillMstr.setOtherStoreRate(BigDecimal.ZERO);
//                appUserBillMstr.setOtherStoreAmount(BigDecimal.ZERO);
//            }else{
//                BigDecimal totalAmount = rechargeAmount.add(giveAmount).add(welfareAmount);
//                if(totalAmount.doubleValue() < 0){
//                    totalAmount = totalAmount.multiply(new BigDecimal(-1));
//                }
//                appUserBillMstr.setOtherStoreRate(sysSettlementRate.getOtherStoreRate());
//                appUserBillMstr.setOtherStoreAmount(totalAmount
//                        .multiply(sysSettlementRate.getOtherStoreRate()));
//            }
//            appUserBillMstr.setIsOtherStore(SysBoolType.YES.getCode());
//        }else{
//            appUserBillMstr.setIsOtherStore(SysBoolType.NO.getCode());
//        }

        return appUserBillMstr;
    }


    //<editor-folder desc="基础函数">
    @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) {
        return baseMapper.selectTotalBalanceGroupByAppUser(appUserId, orderType);
    }

    @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
    public String importData(List<RechargePasswordImportDTO> rechargePasswordImportDTOS, RechargeCardBatchRecord rechargeCardBatchRecord) {
        // 保存导入-未使用的充值卡
        this.buildRechargeCard(rechargePasswordImportDTOS, rechargeCardBatchRecord);
        return "导入成功";
    }

    /**
     * 直充导入
     *
     * @param importVOS 充值卡数据列表
     * @return
     */
    @Override
    public String directChargingImportData(List<RechargeBatchImportDTO> importVOS, RechargeCardBatchRecord rechargeCardBatchRecord, List<String> phoneNumbers) {
        Map<String, SysStore> storeMap = sysStoreService.list(new QueryWrapper<SysStore>().lambda()
                        .in(SysStore::getCode, importVOS.stream().filter(item -> StringUtils.isNotEmpty(item.getStoreCode()))
                                .map(RechargeBatchImportDTO::getStoreCode).collect(Collectors.toSet()))).stream()
                .collect(Collectors.toMap(SysStore::getCode, SysStore -> SysStore));
        List<String> phoneNumberList = phoneNumbers.stream().distinct().filter(StrUtil::isNotEmpty).collect(Collectors.toList());

        Map<String, AppUser> appUserMap = appUserService.list(new QueryWrapper<AppUser>().lambda()
                        .in(AppUser::getPhoneNumber, phoneNumberList)).stream()
                .collect(Collectors.toMap(AppUser::getPhoneNumber, AppUser -> AppUser));

        this.buildDirectCharging(importVOS, rechargeCardBatchRecord, storeMap, appUserMap);

        return "导入成功";
    }

    /**
     * 保存导入-未使用的充值卡
     *
     * @param rechargePasswordImportDTOS
     * @param rechargeCardBatchRecord
     */
    @Transactional(rollbackFor = Exception.class)
    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);
    }

    /**
     * 保存直充
     *
     * @param importVOS
     */
    @Transactional(rollbackFor = Exception.class)
    public void buildDirectCharging(List<RechargeBatchImportDTO> importVOS, RechargeCardBatchRecord rechargeCardBatchRecord, Map<String, SysStore> storeMap, Map<String, AppUser> appUserMap) {
        List<RechargePasswordCard> rechargePasswordCards = new ArrayList<>();
        for (RechargeBatchImportDTO importDTO : importVOS) {
            RechargePasswordCard rechargePasswordCard = new RechargePasswordCard();
            rechargePasswordCard.setBatchNo(rechargeCardBatchRecord.getBatchNo());
            rechargePasswordCard.setCardNo(orderNoUtils.getOrderNo());
            rechargePasswordCard.setPassword(Utils.getPassWordOne(8));
            rechargePasswordCard.setCreateType(RechargeCreateType.IMPORT.getCode());
            rechargePasswordCard.setRechargeAmount(importDTO.getRechargeAmount());
            rechargePasswordCard.setGiveAmount(BigDecimal.ZERO);
            rechargePasswordCard.setGivePointAmount(0);
            rechargePasswordCard.setRechargeTime(DateUtils.getNowDate());
            rechargePasswordCard.setRechargeBalance(rechargePasswordCard.getRechargeAmount());
            rechargePasswordCard.setGiveBalance(rechargePasswordCard.getGiveAmount());
            rechargePasswordCard.setDelFlag(DeleteStatus.OK.getCode());
            rechargePasswordCard.setRechargeStatus(RechargeStatusType.HAS_USE.getCode());
            rechargePasswordCard.setRechargeUserId(appUserMap.get(importDTO.getAppUserPhoneNumber()).getId());
            rechargePasswordCard.setIsSupportLife(SysBoolType.YES.getCode());
            rechargePasswordCard.setIsSupportGoods(SysBoolType.YES.getCode());
            rechargePasswordCard.setIsSupportCloth(SysBoolType.YES.getCode());
            rechargePasswordCard.setIsSupportCar(SysBoolType.YES.getCode());
            // 设置客户星级
            rechargePasswordCard.setCreateById(rechargeCardBatchRecord.getCreateById());
            rechargePasswordCard.setCreateBy(rechargeCardBatchRecord.getCreateBy());
            rechargePasswordCard.setCreateTime(DateUtils.getNowDate());
            if (CollUtil.isNotEmpty(storeMap) && storeMap.get(importDTO.getStoreCode()) != null) {
                rechargePasswordCard.setRechargeStoreId(storeMap.get(importDTO.getStoreCode()).getId());
                rechargePasswordCard.setUseBindStoreId(storeMap.get(importDTO.getStoreCode()).getId());
            }
            rechargePasswordCards.add(rechargePasswordCard);
        }
        this.saveBatch(rechargePasswordCards);
        for (RechargePasswordCard rechargePasswordCard : rechargePasswordCards) {
            // 保存订单
            OrderRecharge orderRecharge = orderRechargeService.buildOrderRechargeByCardPassword(rechargePasswordCard, OrderRechargeCreateDTO.buildDirectChargingCardByOrder(rechargePasswordCard.getRechargeUserId()));
            // 保存消费日志
            appUserBillMstrService.consumeRecord(ConsumeOrderDTO.buildOrderRechargeData(orderRecharge));
            rechargePasswordCard.setOrderNo(orderRecharge.getOrderNo());
            this.updateById(rechargePasswordCard);
        }
    }


    /**
     * 保存批次号信息
     *
     * @param batchName
     * @param expireTime
     * @param remark
     * @param starLevel
     * @return
     */
    @Override
    public RechargeCardBatchRecord buildRechargeCardBatchRecord(String batchName, Date expireTime, String remark, Integer starLevel, String isDirectRecharge) {
        RechargeCardBatchRecord rechargeCardBatchRecord = new RechargeCardBatchRecord();
        rechargeCardBatchRecord.buildCreateData();
        rechargeCardBatchRecord.setBatchNo(orderNoUtils.getOrderNo());
        rechargeCardBatchRecord.setBatchName(batchName);
        rechargeCardBatchRecord.setLastExpireTime(expireTime);
        rechargeCardBatchRecord.setRemark(remark);
        rechargeCardBatchRecord.setStarLevel(starLevel);
        rechargeCardBatchRecord.setIsDirectRecharge(isDirectRecharge);
        rechargeCardBatchRecordService.save(rechargeCardBatchRecord);
        return rechargeCardBatchRecord;
    }


    /**
     * 按客户获取充值卡信息
     */
    @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, weAppCardRecordByCardDTO.getRechargePasswordCardId())
                .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("该用户余额不足");
        }
        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(rechargeCardPayDTO.getPayAmount());
                } 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();
            baseMapper.updateById(rechargePasswordCard);
            //保存日志
            BillMstrOrderDTO billMstrOrderDTO = new BillMstrOrderDTO();
            billMstrOrderDTO.setAppUserId(rechargeCardPayDTO.getAppUserId());
            billMstrOrderDTO.setStoreId(rechargeCardPayDTO.getStoreId());
            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(), JSONUtil.toJsonStr(billMstrOrderDTO));
        }
    }

    @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::getHasRefund, SysBoolType.NO.getCode())
                .eq(AppUserBillMstr::getBillType, "0")
        );
        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("该充值卡已退款，无法撤回");
            }
            rechargePasswordCard.setRechargeBalance(CurrencyUtil.add(rechargePasswordCard.getRechargeBalance(), consumeBillMstr.getRechargePayAmount()));
            rechargePasswordCard.setGiveBalance(CurrencyUtil.add(rechargePasswordCard.getGiveBalance(), consumeBillMstr.getGivePayAmount()));
            rechargePasswordCard.setWelfareBalance(CurrencyUtil.add(rechargePasswordCard.getWelfareBalance(), consumeBillMstr.getWelfarePayAmount()));
            rechargePasswordCard.setRechargeStatus(RechargeStatusType.HAS_USE.getCode());
            baseMapper.updateById(rechargePasswordCard);
            //更新为已退款
            consumeBillMstr.setHasRefund(SysBoolType.YES.getCode());
            appUserBillMstrService.updateById(consumeBillMstr);
            //新增一个充值记录
            //保存日志
            BillMstrOrderDTO billMstrOrderDTO = new BillMstrOrderDTO();
            BeanUtils.copyProperties(consumeBillMstr, billMstrOrderDTO);
            billMstrOrderDTO.setStoreId(consumeBillMstr.getOrgId());
            billMstrOrderDTO.setRechargeCardNo(rechargePasswordCard.getCardNo());
            billMstrOrderDTO.setRemark("充值卡：" + rechargePasswordCard.getCardNo() + "，退款" + consumeBillMstr.getPayTotalAmount().negate() + "元");
            billMstrOrderService.saveRefundBillMstrOrder(billMstrOrderDTO);
            log.info("订单{}，会员卡 {} 退款成功，扣款日志：【{}】", consumeBillMstr.getOrderNo(), billMstrOrderDTO.getRechargeCardNo(), JSONUtil.toJsonStr(billMstrOrderDTO));
        }
        return true;
    }

    //</editor-folder>

}
