package com.czg.service.market.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.czg.account.entity.ShopInfo;
import com.czg.account.entity.ShopUser;
import com.czg.account.service.ShopConfigService;
import com.czg.account.service.ShopInfoService;
import com.czg.account.service.ShopUserService;
import com.czg.constant.TableValueConstant;
import com.czg.exception.CzgException;
import com.czg.market.dto.MemberConfigDTO;
import com.czg.market.dto.MemberLevelDTO;
import com.czg.market.dto.MkRewardCouponDTO;
import com.czg.market.entity.MemberExpFlow;
import com.czg.market.entity.MemberLevelConfig;
import com.czg.market.entity.MemberOrder;
import com.czg.market.entity.TbMemberConfig;
import com.czg.market.enums.PointsConstant;
import com.czg.market.service.*;
import com.czg.market.vo.*;
import com.czg.order.entity.OrderInfo;
import com.czg.order.service.OrderPaymentService;
import com.czg.service.market.enums.OrderStatusEnums;
import com.czg.service.market.mapper.TbMemberConfigMapper;
import com.czg.utils.AssertUtil;
import com.czg.validator.ValidatorUtil;
import com.czg.validator.group.member.MemberLevelCycleRewardGroup;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 会员基础配置 服务层实现。
 *
 * @author zs
 * @since 2025-09-10
 */
@Slf4j
@DubboService
public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper, TbMemberConfig> implements TbMemberConfigService {
    private final List<String> conditionMap = CollUtil.toList("BIND_PHONE", "ORDER", "COST_AMOUNT", "RECHARGE_AMOUNT");

    @Resource
    private MemberLevelConfigService levelConfigService;
    @DubboReference
    private ShopUserService shopUserService;
    @Resource
    private OrderInfoService orderInfoService;
    @DubboReference
    private OrderPaymentService paymentService;
    @Resource
    private MkPointsUserService pointsUserService;
    @Resource
    private MemberOrderService memberOrderService;
    @Resource
    private MemberExpFlowService memberExpFlowService;
    @Resource
    private MkShopCouponRecordService shopCouponRecordService;
    @DubboReference
    private ShopInfoService shopInfoService;
    @DubboReference
    private ShopConfigService shopConfigService;

    @Override
    public MemberConfigVO detail(Long shopId) {
        shopId = shopInfoService.getMainIdByShopId(shopId);
        TbMemberConfig memberConfig = getOne(new QueryWrapper().eq(TbMemberConfig::getShopId, shopId));
        if (memberConfig == null) {
            memberConfig = new TbMemberConfig();
            memberConfig.setShopId(shopId);
            save(memberConfig);
            memberConfig = getOne(new QueryWrapper().eq(TbMemberConfig::getShopId, shopId));
        }

        MemberConfigVO memberConfigVO = BeanUtil.copyProperties(memberConfig, MemberConfigVO.class, "configList", "conditionList");
        if (StrUtil.isNotBlank(memberConfig.getConfigList())) {
            memberConfigVO.setConfigList(JSONArray.parseArray(memberConfig.getConfigList()).toList(MemberConfigDTO.ConfigList.class));
        }

        if (StrUtil.isNotBlank(memberConfig.getConditionList())) {
            memberConfigVO.setConditionList(JSONArray.parseArray(memberConfig.getConditionList()).toList(MemberConfigDTO.condition.class));
        }

        if (StrUtil.isNotBlank(memberConfig.getMemberPriceShopIdList())) {
            memberConfigVO.setMemberPriceShopIdList(JSONArray.parseArray(memberConfig.getMemberPriceShopIdList()).toList(Long.class));
        }

        return memberConfigVO;
    }

    @Override
    public UMemberConfigVO detail(Long shopId, Long userId) {
        MemberConfigVO memberConfigVO = detail(shopId);
        ShopUser shopUserInfo = shopUserService.getShopUserInfo(shopId, userId);
        HashMap<String, Object> conditionMap = new HashMap<>();
        UMemberConfigVO configVO = new UMemberConfigVO();
        configVO.setMemberConfig(memberConfigVO);
        configVO.setConditionMap(conditionMap);
        if (memberConfigVO.getConditionList() != null) {
            for (MemberConfigDTO.condition item : memberConfigVO.getConditionList()) {
                switch (item.getCode()) {
                    case "BIND_PHONE":
                        conditionMap.put("BIND_PHONE", StrUtil.isNotBlank(shopUserInfo.getPhone()));
                        break;
                    case "ORDER":
                        conditionMap.put("ORDER", orderInfoService.count(query().eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getUserId, shopUserInfo.getUserId())
                                .eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode())) >= Integer.parseInt(item.getValue()));

                        break;
                    case "COST_AMOUNT":
                        conditionMap.put("COST_AMOUNT", orderInfoService.getOneAs(query()
                                        .select("IFNULL(sum(pay_amount), 0) as total_amount ")
                                        .eq(OrderInfo::getShopId, shopId)
                                        .eq(OrderInfo::getUserId, shopUserInfo.getUserId())
                                        .eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode()), BigDecimal.class)
                                .compareTo(new BigDecimal(item.getValue())) >= 0);
                        break;
                    case "RECHARGE_AMOUNT":
                        conditionMap.put("RECHARGE_AMOUNT", paymentService.countMemberInAmount(shopId, shopUserInfo.getId())
                                .compareTo(new BigDecimal(item.getValue())) >= 0);
                        break;
                    default:
                        throw new CzgException("会员开通条件类型错误");
                }

            }
        }

        if (shopUserInfo.getMemberLevelId() == null) {
            MemberLevelConfig configServiceOne = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId).orderBy(MemberLevelConfig::getExperienceValue, true)
                    .limit(1));

            configVO.setMemberLevel(configServiceOne == null ? null : levelConfigService.detail(configServiceOne.getId()));
        } else {
            configVO.setMemberLevel(levelConfigService.detail(shopUserInfo.getMemberLevelId()));
        }

        configVO.setMemberLevelList(levelConfigService.listInfo(shopId));
        return configVO;
    }

    @Override
    public Boolean edit(Long shopId, MemberConfigDTO memberDTO) {
        TbMemberConfig memberConfig = getOne(new QueryWrapper().eq(TbMemberConfig::getShopId, shopId));
        BeanUtil.copyProperties(memberDTO, memberConfig);
        if ((memberDTO.getConfigList() == null || memberDTO.getConfigList().isEmpty()) &&
                (memberDTO.getConditionList() == null || memberDTO.getConditionList().isEmpty())) {
            throw new CzgException("会员开通方式必须选择一个");
        }


        if (memberDTO.getConfigList() != null && !memberDTO.getConfigList().isEmpty()) {
            memberDTO.getConfigList().forEach(item -> {
                if (item.getReward() == null && (item.getCouponList() == null || item.getCouponList().isEmpty())) {
                    throw new CzgException("方案列表中赠送成长值和赠送优惠券不能同时为空");
                }
            });
            memberConfig.setConfigList(JSONObject.toJSONString(memberDTO.getConfigList()));
        }

//        if (memberConfig.getConfigList() != null && !memberConfig.getConfigList().isEmpty() &&
//                (memberConfig.getConditionList() != null || !memberConfig.getConditionList().isEmpty())) {
//            throw new CzgException("会员开通方式为单选条件");
//        }

        if (memberDTO.getConditionList() != null && !memberDTO.getConditionList().isEmpty()) {
//            ArrayList<String> conditionList = CollUtil.newArrayList(conditionMap);
            memberDTO.getConditionList().forEach(item -> {
                if (!conditionMap.contains(item.getCode())) {
                    throw new CzgException("条件列表中code值错误");
                }
            });
//            conditionList.forEach(item -> {
//                memberDTO.getConditionList().add(new MemberDTO.condition(item, null));
//            });

            memberConfig.setConditionList(JSONObject.toJSONString(memberDTO.getConditionList()));
        }

        if (memberDTO.getMemberPriceShopIdList() != null && !memberDTO.getMemberPriceShopIdList().isEmpty()) {
            memberConfig.setMemberPriceShopIdList(JSONObject.toJSONString(memberDTO.getMemberPriceShopIdList()));
        }

        shopConfigService.editStatusByShopIdList(memberConfig.getShopId(),
                memberConfig.getIsOpen().intValue() == 1 && memberConfig.getIsMemberPrice() == 1 ? 1 : 0,
                false,
                "is_member_price",
                "ALL".equals(memberConfig.getMemberPriceShopType()) ? "all" : "part",
                StrUtil.isNotBlank(memberConfig.getMemberPriceShopIdList()) ? JSONArray.parseArray(memberConfig.getMemberPriceShopIdList()).toList(Long.class) : new ArrayList<>());

        return updateById(memberConfig, false);


    }

    private void checkLevelDto(Long shopId, MemberLevelDTO levelDTO) {
        long count = levelConfigService.count(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId).eq(MemberLevelConfig::getName, levelDTO.getName()).ne(MemberLevelConfig::getId, levelDTO.getId()));
        if (count > 0) {
            throw new CzgException("会员等级名称已存在");
        }

        MemberLevelConfig lastConfig = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId)
                .lt(MemberLevelConfig::getId, levelDTO.getId())
                .limit(1).orderBy(MemberLevelConfig::getExperienceValue, true).ne(MemberLevelConfig::getId, levelDTO.getId()));
        if (lastConfig == null && levelDTO.getExperienceValue() > 0) {
            throw new CzgException("1级时本字段必须为0");
        } else if (lastConfig != null && levelDTO.getExperienceValue() <= lastConfig.getExperienceValue()) {
            throw new CzgException("会员等级经验值必须大于上一等级经验值");
        }

        if (levelDTO.getIsCycleReward() == 1) {
            if (levelDTO.getCycleRewardPoints() == null && (levelDTO.getCycleRewardCouponList() == null || levelDTO.getCycleRewardCouponList().isEmpty())) {
                throw new CzgException("周期奖励成长值和优惠券不能同时为空");
            }

            ValidatorUtil.validateEntity(levelDTO, MemberLevelCycleRewardGroup.class);
        }
    }

    @Override
    public Boolean addLevel(Long shopId, MemberLevelDTO levelDTO) {
        checkLevelDto(shopId, levelDTO);

        MemberLevelConfig levelConfig = BeanUtil.copyProperties(levelDTO, MemberLevelConfig.class);
        levelConfig.setShopId(shopId);
        if (levelDTO.getCycleRewardCouponList() != null && !levelDTO.getCycleRewardCouponList().isEmpty()) {
            levelConfig.setCycleRewardCouponList(JSONObject.toJSONString(levelDTO.getCycleRewardCouponList()));
        }

        return levelConfigService.save(levelConfig);
    }

    @Override
    public Boolean editLevel(Long shopId, MemberLevelDTO levelDTO) {
        MemberLevelConfig levelConfig = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getId, levelDTO.getId()).eq(MemberLevelConfig::getShopId, shopId));
        Optional.ofNullable(levelConfig).orElseThrow(() -> new CzgException("会员等级不存在"));
        Integer oldVal = levelConfig.getExperienceValue();
        checkLevelDto(shopId, levelDTO);
        BeanUtil.copyProperties(levelDTO, levelConfig);

        if (levelDTO.getCycleRewardCouponList() != null && !levelDTO.getCycleRewardCouponList().isEmpty()) {
            levelConfig.setCycleRewardCouponList(JSONObject.toJSONString(levelDTO.getCycleRewardCouponList()));
        } else {
            levelConfig.setCycleRewardCouponList(null);
        }
        AssertUtil.isTrue(!levelConfigService.updateById(levelConfig, false), "修改失败");

        Long mainShopid = shopInfoService.getMainIdByShopId(shopId);
        if (!levelDTO.getExperienceValue().equals(oldVal)) {
            List<ShopUser> shopUserList = shopUserService.list(new QueryWrapper().eq(ShopUser::getMainShopId, mainShopid));
            shopUserList.forEach(item -> {
                MemberLevelConfig configServiceOne = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, mainShopid)
                        .le(MemberLevelConfig::getExperienceValue, item.getExperience()).orderBy(MemberLevelConfig::getExperienceValue, false).limit(1));
                item.setMemberLevelId(configServiceOne == null ? item.getMemberLevelId() : configServiceOne.getId());
            });
            return shopUserService.updateBatch(shopUserList);
        }

        return true;
    }

    @Override
    public ArrayList<MemberLevelVO> listLevel(Long shopId) {
        shopId = shopInfoService.getMainIdByShopId(shopId);
        ArrayList<MemberLevelVO> memberLevels = new ArrayList<>();
        levelConfigService.list(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId)).forEach(item -> {
            MemberLevelVO memberLevelVO = BeanUtil.copyProperties(item, MemberLevelVO.class, "cycleRewardCouponList");
            if (StrUtil.isNotBlank(item.getCycleRewardCouponList())) {
                memberLevelVO.setCycleRewardCouponList(JSONArray.parseArray(item.getCycleRewardCouponList()).toList(MemberLevelDTO.ConfigCoupon.class));
            }
            memberLevels.add(memberLevelVO);
        });

        return memberLevels;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deliver(ShopUser shopUser, TableValueConstant.MemberExpFlow.Type type, BigDecimal money, Integer expVal, Long sourceId) {
        if (shopUser == null || shopUser.getIsVip() == 0) {
            return false;
        }
        if (shopUser.getMemberLevelId() == null) {
            log.warn("会员等级不存在, 店铺id: {}, 用户id: {}", shopUser.getMainShopId(), shopUser.getUserId());
            return false;
        }
        MemberConfigVO memberConfig = detail(shopUser.getMainShopId());
        if (memberConfig == null) {
            log.warn("会员配置不存在, 店铺id: {}", shopUser.getMainShopId());
            return false;
        }
        ShopUser upShopUser = new ShopUser();
        upShopUser.setId(shopUser.getId());
        if (shopUser.getExperience() == null) {
            upShopUser.setExperience(0L);
        }

        MemberLevelVO levelVO = levelConfigService.detail(shopUser.getMemberLevelId());
        if (levelVO == null) {
            log.warn("会员等级配置不存在, 店铺id: {}, 等级id: {}", shopUser.getMainShopId(), shopUser.getMemberLevelId());
            return false;
        }

        log.info("会员奖励发放，类型: {}， 金额: {}, userId: {}, 经验值: {}", type.getCode(), money, shopUser.getUserId(), expVal);
        long exp = 0;
        switch (type) {
            case COST -> {
                if (memberConfig.getCostReward() != null) {
                    exp = money.longValue() * memberConfig.getCostReward();
                }
            }
            case RECHARGE -> {
                if (memberConfig.getRechargeReward() != null) {
                    exp = money.longValue() * memberConfig.getRechargeReward();
                }
            }
            case PAY -> exp = expVal;
            case MEMBER_TASK -> {
                if (levelVO.getIsCycleReward() == 1) {
                    if (levelVO.getCycleRewardPoints() != null) {
                        int points = levelVO.getCycleRewardPoints();
                        //会员周期发放积分
                        pointsUserService.alterPoints(null, shopUser.getId(), shopUser.getMainShopId(), PointsConstant.ADD, points, sourceId, "会员周期发放");
                    }

                    if (levelVO.getCycleRewardCouponList() != null && !levelVO.getCycleRewardCouponList().isEmpty()) {
                        levelVO.getCycleRewardCouponList().forEach(item ->
                                shopCouponRecordService.grant(shopUser.getMainShopId(), new MkRewardCouponDTO().setCouponId(item.getCoupon().getId())
                                        .setNum(item.getNum())
                                        .setUserId(shopUser.getUserId())
                                        .setShopId(shopUser.getMainShopId()), "购买会员赠券"));
                    }
                }

            }

        }

        if (exp > 0) {
            MemberExpFlow expFlow = new MemberExpFlow();
            expFlow.setContent(type.getMsg() + exp);
            expFlow.setType("+");
            expFlow.setUserId(shopUser.getUserId());
            expFlow.setShopId(shopUser.getMainShopId());
            expFlow.setMoney(money);
            expFlow.setValue(exp);
            expFlow.setSourceId(sourceId);
            memberExpFlowService.save(expFlow);

            upShopUser.setExperience(shopUser.getExperience() + exp);
            shopUser.setExperience(upShopUser.getExperience());
            // 修改会员等级
            MemberLevelConfig nextConfig = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopUser.getMainShopId())
                    .gt(MemberLevelConfig::getExperienceValue, levelVO.getExperienceValue()).orderBy(MemberLevelConfig::getExperienceValue, true).limit(1));
            if (nextConfig != null && shopUser.getExperience() >= nextConfig.getExperienceValue()) {
                upShopUser.setMemberLevelId(nextConfig.getId());
            }
            shopUserService.updateInfo(upShopUser);
        }

        log.info("用户id: {}, 增加经验值: {}, 当前经验值: {}, 当前等级: {}", shopUser.getUserId(), exp, shopUser.getExperience(), shopUser.getMemberLevelId());

        return true;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean joinMemberByCondition(Long shopId, Long userId, ShopUser shopUser) {
        if (shopUser == null) {
            log.warn("用户不存在, 店铺id: {}, 用户id: {}", shopId, userId);
            return false;
        }
        if (shopUser.getIsVip() == 1 && shopUser.getStartTime() != null && shopUser.getEndTime() != null &&
                DateUtil.isIn(DateUtil.date(), DateUtil.date(shopUser.getStartTime()), DateUtil.date(shopUser.getEndTime()))) {
            return false;
        }
        MemberConfigVO memberConfigVO = detail(shopId);
        if (!memberConfigVO.getIsOpen().equals(1L)) {
            log.info("超级会员未开启, 店铺id: {}", shopId);
            return false;
        }
        MemberLevelConfig levelConfig = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId).orderBy(MemberLevelConfig::getExperienceValue, true).limit(1));
        if (levelConfig == null) {
            log.info("会员等级配置不存在, 店铺id: {}", shopId);
            return false;
        }
        if (!"CONDITION".equals(memberConfigVO.getOpenType())) {
            return false;
        }

        if (CollUtil.isEmpty(memberConfigVO.getConditionList())) {
            log.info("会员开通条件不存在, 店铺id: {}", shopId);
            return false;
        }

        for (MemberConfigDTO.condition item : memberConfigVO.getConditionList()) {
            boolean canOpen = switch (item.getCode()) {
                case "BIND_PHONE" -> StrUtil.isNotBlank(shopUser.getPhone());
                case "ORDER" ->
                        orderInfoService.count(query().eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getUserId, shopUser.getUserId())
                                .eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode())) >= Integer.parseInt(item.getValue());
                case "COST_AMOUNT" ->
                        orderInfoService.getOneAs(query().select("IFNULL(sum(pay_amount), 0) as total_amount").eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getUserId, shopUser.getUserId())
                                        .eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode()), BigDecimal.class)
                                .compareTo(new BigDecimal(item.getValue())) >= 0;
                case "RECHARGE_AMOUNT" -> paymentService.countMemberInAmount(shopId, shopUser.getId())
                        .compareTo(new BigDecimal(item.getValue())) >= 0;
                default -> throw new CzgException("会员开通条件类型错误");
            };
            if (!canOpen) {
                log.info("用户id: {}, 会员开通条件不满足", userId);
                return false;
            }
        }
        ShopUser upShopUser = new ShopUser();
        upShopUser.setId(shopUser.getId());
        upShopUser.setMemberLevelId(levelConfig.getId());
        upShopUser.setStartTime(LocalDateTime.now());
        upShopUser.setEndTime(upShopUser.getStartTime().plusDays(20000));
        upShopUser.setIsVip(1);
        shopUser.setIsVip(1);
        if (shopUser.getJoinTime() != null) {
            upShopUser.setJoinTime(LocalDateTime.now());
        }
        upShopUser.setOpenType("CONDITION");
        return shopUserService.updateById(upShopUser);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean joinMember(Long shopId, Long userId, Long memberOrderId) {
        MemberConfigVO memberConfigVO = detail(shopId);
        ShopUser shopUser = shopUserService.getShopUserInfo(shopId, userId);
        if (shopUser == null) {
            log.warn("用户不存在, 店铺id: {}, 用户id: {}", shopId, userId);
            return false;
        }
        MemberLevelConfig levelConfig = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId).orderBy(MemberLevelConfig::getExperienceValue, true).limit(1));

        // 条件开通
        if (memberConfigVO.getConfigList() == null || memberConfigVO.getConfigList().isEmpty()) {
            throw new CzgException("会员开通方案未配置，请联系店铺");
        }

        if (shopUser.getStartTime() == null || shopUser.getEndTime().isBefore(DateUtil.date().toLocalDateTime())) {
            shopUser.setStartTime(DateUtil.date().toLocalDateTime());
        }
        if (shopUser.getEndTime() == null || shopUser.getEndTime().isBefore(DateUtil.date().toLocalDateTime())) {
            shopUser.setEndTime(DateUtil.date().toLocalDateTime());
        }

        MemberOrder memberOrder = memberOrderService.getOne(new QueryWrapper().eq(MemberOrder::getId, memberOrderId).eq(MemberOrder::getShopId, shopId));
        if (memberOrder == null) {
            log.warn("会员购买支付失败，会员订单不存在，会员订单id：{}", memberOrderId);
            return false;
        }
        if (!OrderStatusEnums.UNPAID.getCode().equals(memberOrder.getStatus())) {
            log.warn("会员购买支付失败，会员订单状态不为待支付，会员订单id：{}", memberOrderId);
            return false;
        }

        switch (memberOrder.getCircleUnit()) {
            case "天":
                shopUser.setEndTime(shopUser.getEndTime().plusDays(memberOrder.getCircleTime()));
                break;
            case "周":
                shopUser.setEndTime(shopUser.getEndTime().plusWeeks(memberOrder.getCircleTime()));
                break;
            case "月":
                shopUser.setEndTime(shopUser.getEndTime().plusMonths(memberOrder.getCircleTime()));
                break;
            case "季":
                shopUser.setEndTime(shopUser.getEndTime().plusMonths(memberOrder.getCircleTime() * 3L));
                break;
            case "年":
                shopUser.setEndTime(shopUser.getEndTime().plusYears(memberOrder.getCircleTime()));
                break;
            default:
                throw new CzgException("周期单位错误");
        }

        shopUser.setMemberName(memberOrder.getName());


        // 发券流程
        if (StrUtil.isNotBlank(memberOrder.getCouponList())) {
            JSONArray.parseArray(memberOrder.getCouponList()).toJavaList(MemberConfigDTO.ConfigCoupon.class).forEach(item -> {
                try {
                    shopCouponRecordService.grant(shopId, new MkRewardCouponDTO().setCouponId(item.getCoupon().getId())
                            .setNum(item.getNum())
                            .setUserId(shopUser.getUserId())
                            .setShopId(shopId), "购买会员赠券");
                } catch (Exception e) {
                    log.error("发券失败", e);
                }

            });
        }


        memberOrder.setPayAmount(memberOrder.getAmount());
        memberOrder.setStatus(OrderStatusEnums.DONE.getCode());
        memberOrderService.updateById(memberOrder);

        if (shopUser.getMemberLevelId() == null || shopUser.getMemberLevelId() == 0) {
            shopUser.setMemberLevelId(levelConfig.getId());
        }
        shopUser.setMemberCircleName(memberOrder.getName());
        shopUser.setMemberCircleReward(memberOrder.getReward());
        shopUser.setIsVip(1);
        shopUser.setOpenType("PAY");
        shopUser.setJoinTime(LocalDateTime.now());
        if (memberOrder.getReward() != null) {
            //购买开通
            deliver(shopUser, TableValueConstant.MemberExpFlow.Type.PAY, memberOrder.getAmount(), memberOrder.getReward(), memberOrderId);
        }
        return shopUserService.updateInfo(shopUser);
    }

    @Override
    public List<MemberListVO> getMemberList(Long userId) {
        List<ShopUser> shopUsers = shopUserService.list(new QueryWrapper().eq(ShopUser::getUserId, userId));
        if (shopUsers.isEmpty()) {
            return new ArrayList<>();
        }
        Set<Long> shopIdList = shopUsers.stream().map(ShopUser::getSourceShopId).collect(Collectors.toSet());
        Map<Long, ShopInfo> shopInfoMap = shopInfoService.list(new QueryWrapper().in(ShopInfo::getId, shopIdList)).stream().collect(Collectors.toMap(ShopInfo::getId, item -> item));
        ArrayList<MemberListVO> memberLists = new ArrayList<>();
        shopUsers.forEach(shopUser -> {
            if (shopUser.getStartTime() != null && shopUser.getEndTime() != null && DateUtil.isIn(DateUtil.date(), DateUtil.date(shopUser.getStartTime()), DateUtil.date(shopUser.getEndTime()))) {
                ShopInfo shopInfo = shopInfoMap.getOrDefault(shopUser.getSourceShopId(), new ShopInfo());
                memberLists.add(new MemberListVO().setShopName(shopInfo.getShopName())
                        .setShopId(shopInfo.getId())
                        .setLogo(shopInfo.getLogo()));
            } else {
                shopUser.setIsVip(0);
                shopUserService.updateById(shopUser);
            }
        });

        return memberLists;
    }

    @Override
    @Transactional
    public MemberDetailVO getUserDetail(Long userId, Long shopId) {
        ShopInfo shopInfo = shopInfoService.getById(shopId);
        Long mainIdByShopId = shopInfo.getMainId() == null ? shopId : shopInfo.getMainId();
        ShopUser shopUser = shopUserService.getOne(new QueryWrapper().eq(ShopUser::getUserId, userId).eq(ShopUser::getMainShopId, mainIdByShopId));
        MemberLevelVO levelVO = null;
        if (shopUser.getMemberLevelId() != null) {
            levelVO = levelConfigService.detail(shopUser.getMemberLevelId());
        }
        MemberConfigVO memberConfig = detail(shopId);
        long nextLevelExperience = 0;
        if (memberConfig != null && memberConfig.getIsOpen() == 1) {
            if ("CONDITION".equals(memberConfig.getOpenType())) {
                joinMemberByCondition(shopId, userId, shopUser);
            }
            MemberLevelConfig nextLevel = levelConfigService.getOne(new QueryWrapper()
                    .eq(MemberLevelConfig::getShopId, mainIdByShopId)
                    .ge(MemberLevelConfig::getExperienceValue, shopUser.getExperience())
                    .ne(MemberLevelConfig::getId, shopUser.getMemberLevelId()).orderBy(MemberLevelConfig::getExperienceValue, true));
            if (nextLevel != null) {
                nextLevelExperience = nextLevel.getExperienceValue() - shopUser.getExperience();
            }
        }
        return new MemberDetailVO()
                .setMemberCircleName(shopUser.getMemberCircleName())
                .setMemberCircleReward(shopUser.getMemberCircleReward())
                .setMemberName(shopUser.getMemberName())
                .setShopInfo(shopInfo)
                .setMemberLevel(levelVO)
                .setExperience(shopUser.getExperience())
                .setEndTime(shopUser.getEndTime())
                .setNextExperienceValue(nextLevelExperience);
    }
}
