
package com.tmerclub.cloud.user.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.tmerclub.cloud.api.auth.constant.SysTypeEnum;
import com.tmerclub.cloud.api.auth.dto.AuthAccountDTO;
import com.tmerclub.cloud.api.auth.dto.AuthAccountWithSocialDTO;
import com.tmerclub.cloud.api.auth.dto.AuthSocialDTO;
import com.tmerclub.cloud.api.auth.feign.AccountFeignClient;
import com.tmerclub.cloud.api.auth.feign.TokenFeignClient;
import com.tmerclub.cloud.api.auth.vo.AuthAccountVO;
import com.tmerclub.cloud.api.coupon.feign.CouponFeignClient;
import com.tmerclub.cloud.api.coupon.vo.CouponUserCountDataVO;
import com.tmerclub.cloud.api.distribution.bo.DistributionUserUpdateBO;
import com.tmerclub.cloud.api.distribution.feign.DistributionFeignClient;
import com.tmerclub.cloud.api.order.dto.QueryOrderDTO;
import com.tmerclub.cloud.api.order.feign.OrderFeignClient;
import com.tmerclub.cloud.api.payment.allinpay.member.resp.PersonalMemberInfo;
import com.tmerclub.cloud.api.payment.constant.PaySysType;
import com.tmerclub.cloud.api.payment.feign.AllinpayFeignClient;
import com.tmerclub.cloud.api.payment.vo.PaySettlementConfigVO;
import com.tmerclub.cloud.api.platform.feign.ConfigFeignClient;
import com.tmerclub.cloud.api.user.bo.UidAndUserIdBO;
import com.tmerclub.cloud.api.user.vo.MemberOverviewVO;
import com.tmerclub.cloud.api.user.vo.UserApiVO;
import com.tmerclub.cloud.api.user.vo.UserManagerVO;
import com.tmerclub.cloud.common.bean.PaySettlementConfig;
import com.tmerclub.cloud.common.cache.constant.UserCacheNames;
import com.tmerclub.cloud.common.cache.util.RedisUtil;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.database.dto.PageDTO;
import com.tmerclub.cloud.common.database.util.PageAdapter;
import com.tmerclub.cloud.common.database.util.PageUtil;
import com.tmerclub.cloud.common.database.vo.PageVO;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.leaf.manager.SegmentManager;
import com.tmerclub.cloud.common.order.vo.UserOrderStatisticVO;
import com.tmerclub.cloud.common.response.ResponseEnum;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.rocketmq.config.RocketMqConstant;
import com.tmerclub.cloud.common.security.AuthUserContext;
import com.tmerclub.cloud.common.util.IpHelper;
import com.tmerclub.cloud.common.util.Json;
import com.tmerclub.cloud.common.util.PriceUtil;
import com.tmerclub.cloud.user.bo.mongo.MongoUserScoreLogBO;
import com.tmerclub.cloud.user.constant.DistributedIdKey;
import com.tmerclub.cloud.user.constant.LevelTypeEnum;
import com.tmerclub.cloud.user.constant.OrderSortEnum;
import com.tmerclub.cloud.user.dto.ShopCustomerDTO;
import com.tmerclub.cloud.user.dto.UserDTO;
import com.tmerclub.cloud.user.dto.UserManagerDTO;
import com.tmerclub.cloud.user.mapper.UserMapper;
import com.tmerclub.cloud.user.model.User;
import com.tmerclub.cloud.user.model.UserExtension;
import com.tmerclub.cloud.user.service.*;
import com.tmerclub.cloud.user.vo.UserVO;
import io.seata.common.util.CollectionUtils;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

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

/**
 * 用户表
 *
 * @author YXF
 * @date 2020-12-08 11:18:04
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserExtensionService userExtensionService;
    @Autowired
    private UserLevelService userLevelService;
    @Autowired
    private UserAddrService userAddrService;
    @Autowired
    private UserConsigneeService userConsigneeService;
    @Autowired
    private UserGrowthLogService userGrowthLogService;
    @Autowired
    private UserScoreGetLogService userScoreGetLogService;
    @Autowired
    private UserScoreLockService userScoreLockService;
    @Autowired
    private UserScoreLogService userScoreLogService;
    @Autowired
    private UserTagUserService userTagUserService;
    @Autowired
    private SegmentManager segmentManager;
    @Autowired
    private RocketMQTemplate userNotifyDistributionUserTemplate;
    @Autowired
    private ShopCustomerService shopCustomerService;
    @DubboReference
    private AccountFeignClient accountFeignClient;
    @DubboReference
    private TokenFeignClient tokenFeignClient;
    @DubboReference
    private OrderFeignClient orderFeignClient;
    @DubboReference
    private CouponFeignClient couponFeignClient;
    @DubboReference
    private AllinpayFeignClient allinpayFeignClient;
    @DubboReference
    private ConfigFeignClient configFeignClient;
    @DubboReference
    private DistributionFeignClient distributionFeignClient;
    @Autowired
    private UserBalanceLogService userBalanceLogService;

    @Override
    public PageVO<UserApiVO> page(PageDTO pageDTO, UserManagerDTO userManagerDTO) {
        return PageUtil.doPage(pageDTO, () -> userMapper.list(userManagerDTO));
    }

    @Override
    @Cacheable(cacheNames = UserCacheNames.USER_INFO, key = "#userId")
    public UserApiVO getByUserId(Long userId) {
        UserApiVO userApiVO = userMapper.getByUserId(userId);
        if (Objects.isNull(userApiVO)) {
            return null;
        }
        ServerResponseEntity<AuthAccountVO> accountResponse = accountFeignClient.getInsiderDataByUserIdAndSysType(userId, SysTypeEnum.ORDINARY.value());
        if (!accountResponse.isSuccess()) {
            throw new LuckException(accountResponse.getMsg());
        }
        if (Objects.nonNull(accountResponse.getData())) {
            userApiVO.setUserName(accountResponse.getData().getUsername());
        }

        return userApiVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = UserCacheNames.USER_INFO, key = "#user.userId")
    public void update(User user) {
        userMapper.update(user);
        // USER_NOTIFY_DISTRIBUTION_USER_TOPIC
        // 如果有一项不为空，修改分销员信息（如果是分销员）
        if (StrUtil.isNotBlank(user.getPic()) || StrUtil.isNotBlank(user.getNickName())) {
            DistributionUserUpdateBO distributionUserUpdateBO = new DistributionUserUpdateBO();
            distributionUserUpdateBO.setUserId(user.getUserId());
            distributionUserUpdateBO.setNickName(user.getNickName());
            distributionUserUpdateBO.setPic(user.getPic());
            //通知分销服务， 修改分销员的昵称和分销员的头像
            SendStatus sendStockStatus = userNotifyDistributionUserTemplate.syncSend(RocketMqConstant.USER_NOTIFY_DISTRIBUTION_USER_TOPIC, new GenericMessage<>(distributionUserUpdateBO)).getSendStatus();
            if (!Objects.equals(sendStockStatus, SendStatus.SEND_OK)) {
                throw new LuckException(ResponseEnum.EXCEPTION);
            }
        }
    }

    @Override
    @CacheEvict(cacheNames = UserCacheNames.USER_INFO, key = "#userId")
    public void removeUserCacheByUserId(Long userId) {
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserLevel(Integer level, int minGrowth, Integer maxGrowth) {
        userMapper.updateUserLevel(level, minGrowth, maxGrowth);
        userExtensionService.updateUserLevel(level, minGrowth, maxGrowth);
    }

    @Override
    public List<UserApiVO> getUserByUserIds(List<Long> userIds) {
        if (CollUtil.isEmpty(userIds)) {
            return new ArrayList<>(0);
        }
        return userMapper.getUserByUserIds(userIds);
    }

    @Override
    public UserApiVO getUserAndOpenIdsByUserId(Long userId) {
        UserApiVO userApiVO = userMapper.getByUserId(userId);
        List<String> ids = accountFeignClient.getBizUserIdListByUserId(userId).getData();
        if(CollUtil.isNotEmpty(ids)){
            userApiVO.setBizUserIdList(ids);
        }
        return userApiVO;
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    public UidAndUserIdBO save(String mobile, String password, String tempUid) {
        Long userId = segmentManager.getSegmentId(DistributedIdKey.tmerclub_USER);
        AuthAccountDTO authAccountDTO = getAuthAccountDTO(mobile, password, userId);
        AuthAccountWithSocialDTO authAccountWithSocialDTO = new AuthAccountWithSocialDTO();
        authAccountWithSocialDTO.setAuthAccount(authAccountDTO);
        authAccountWithSocialDTO.setTempUid(tempUid);
        User user = new User();
        user.setUserId(userId);
        user.setLevel(Constant.USER_LEVEL_INIT);
        user.setLevelType(LevelTypeEnum.ORDINARY_USER.value());
        user.setStatus(1);
        user.setPhone(authAccountDTO.getPhone());
        // 昵称默认位u + 手机尾号后4位
        user.setNickName("u" + mobile.substring(7));
        // 默认开启商品个性化推荐
        user.setProdRecommendation(1);
        // 这里保存之后才有用户id
        userMapper.save(user);
        // 有多个用户使用同一个手机号注册-证明当前添加的用户是重复注册，抛出异常回滚当前注册的用户
        int count = userMapper.countUserByPhone(mobile);
        if (count > 1) {
            throw new LuckException("手机号已存在，请更换手机号再次尝试");
        }

        // 保存统一账户信息
        ServerResponseEntity<Long> serverResponse = accountFeignClient.saveAccountWithSocial(authAccountWithSocialDTO);
        // 抛异常回滚
        if (!serverResponse.isSuccess()) {
            throw new LuckException(serverResponse.getMsg());
        }

        UserExtension userExtension = new UserExtension();
        userExtension.setBalance(0L);
        userExtension.setActualBalance(0L);
        userExtension.setAllinpayBalance(0L);
        userExtension.setAllinpayActualBalance(0L);
        userExtension.setAllinpayRealNameSet(0);
        userExtension.setAllinpayPhoneBind(0);
        userExtension.setAllinpayPayPwdSet(0);
        userExtension.setAllinpayProtocolSign(0);
        userExtension.setAllinpayPayAcctBind(0);
        userExtension.setGrowth(0);
        userExtension.setLevel(1);
        userExtension.setLevelType(0);
        userExtension.setScore(0L);
        userExtension.setVersion(0);
        userExtension.setSignDay(0);
        // 上面保存这边才能拿到userId
        userExtension.setUserId(user.getUserId());

        userExtensionService.save(userExtension);
        //用户注册成功后初始化用户数据
        MongoUserScoreLogBO mongoUserScoreLogBO = userLevelService.initUserInfoAndLevelInfo(userExtension, Constant.USER_LEVEL_INIT, LevelTypeEnum.ORDINARY_USER.value(), authAccountDTO.getPhone());

        // 判断是否开启通联支付
        boolean isAllinpay = false;
        String data = configFeignClient.getConfig(Constant.PAY_SETTLEMENT_CONFIG).getData();
        if (!ObjectUtils.isEmpty(data)) {
            PaySettlementConfig config = JSON.parseObject(data, PaySettlementConfig.class);
            isAllinpay = config.getPaySettlementType() != null
                    && Objects.equals(config.getPaySettlementType(), PaySysType.ALLINPAY.value());
        }
        if (isAllinpay) {
            // 若开通则同步创建通联个人会员
            allinpayFeignClient.batchCreatePersonalMember(Collections.singletonList(user.getUserId().toString()));
            // 是否第三方注册登录，是则绑定对应的支付标识
            if (!ObjectUtils.isEmpty(tempUid)) {
                AuthSocialDTO authSocial = accountFeignClient.getBizUserIdByTempUid(tempUid).getData();
                if (!ObjectUtils.isEmpty(authSocial)) {
                    allinpayFeignClient.bindPayAcct(userId, authSocial.getBizUserId(), authSocial.getSocialType());
                }
                // 并更新用户扩展信息
                userExtension = userExtensionService.getByUserId(userId);
                userExtension.setAllinpayPayAcctBind(1);
                userExtensionService.update(userExtension);
            }
        }
        if (Objects.nonNull(mongoUserScoreLogBO)) {
            userScoreLogService.saveToMongdb(mongoUserScoreLogBO);
        }
        return new UidAndUserIdBO(serverResponse.getData(), userId);
    }

    private static AuthAccountDTO getAuthAccountDTO(String mobile, String password, Long userId) {
        AuthAccountDTO authAccountDTO = new AuthAccountDTO();
        authAccountDTO.setCreateIp(IpHelper.getIpAddr());
        authAccountDTO.setPassword(password);
        authAccountDTO.setPhone(mobile);
        authAccountDTO.setIsAdmin(0);
        authAccountDTO.setSysType(SysTypeEnum.ORDINARY.value());
        authAccountDTO.setStatus(1);
        authAccountDTO.setUserId(userId);
        return authAccountDTO;
    }

    @Override
    @CacheEvict(cacheNames = UserCacheNames.USER_INFO, key = "#userId")
    @GlobalTransactional(rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    public void updateUserMobile(Long userId, String mobile) {
        AuthAccountDTO authAccountDTO = new AuthAccountDTO();
        authAccountDTO.setUserId(userId);
        authAccountDTO.setPhone(mobile);
        authAccountDTO.setSysType(SysTypeEnum.ORDINARY.value());
        ServerResponseEntity<Void> voidServerResponseEntity = accountFeignClient.updateUserMobile(authAccountDTO);
        if (!voidServerResponseEntity.isSuccess()) {
            throw new LuckException(voidServerResponseEntity.getMsg());
        }
        // 更新user表手机号
        User user = new User();
        user.setUserId(userId);
        user.setPhone(mobile);
        userMapper.update(user);
        // 同步修改分销员手机号
        DistributionUserUpdateBO distributionUserUpdateBO = new DistributionUserUpdateBO();
        distributionUserUpdateBO.setUserId(user.getUserId());
        distributionUserUpdateBO.setUserMobile((user.getPhone()));
        SendStatus sendStockStatus = userNotifyDistributionUserTemplate.syncSend(RocketMqConstant.USER_NOTIFY_DISTRIBUTION_USER_TOPIC, new GenericMessage<>(distributionUserUpdateBO)).getSendStatus();
        if (!Objects.equals(sendStockStatus, SendStatus.SEND_OK)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }

    @Override
    public PageVO<UserManagerVO> getUserInfoPage(PageDTO pageDTO, UserManagerDTO userManagerDTO) {
        PageVO<UserManagerVO> pageVO = new PageVO<>();
        // 用户信息
        Long userTotal = userMapper.countUserPageByParam(userManagerDTO);
        pageVO.setTotal(userTotal);
        pageVO.setPages(PageUtil.getPages(pageVO.getTotal(), pageDTO.getPageSize()));
        if (Objects.equals(0L, userTotal)) {
            pageVO.setList(Collections.emptyList());
            return pageVO;
        }
        List<UserManagerVO> userList = getUserInfoList(pageDTO, userManagerDTO);
        pageVO.setList(userList);
        return pageVO;
    }

    @Override
    public List<UserManagerVO> getUserInfoList(PageDTO pageDTO, UserManagerDTO userManagerDTO) {
        // 补充系统支付类型
        userManagerDTO.setPaySysType(configFeignClient.getPaySysType().getData());
        // 从用户表中查询数据，并且初始化一些相关订单变量的数据，就不用在后面再次设置相关相关初始值了
        List<UserManagerVO> userList = userMapper.listUserByParam(userManagerDTO, new PageAdapter(pageDTO));
        // 补充余额记录数据
        userList = userBalanceLogService.setUserInfo(userList);
        // 补充积分记录数据
        userList = userScoreLogService.setUserInfo(userList);
        for (UserManagerVO userManagerVO : userList) {
            // 将余额由分转为元
            BigDecimal currentBalance = userManagerVO.getCurrentBalance();
            BigDecimal sumBalance = userManagerVO.getSumBalance();
            userManagerVO.setCurrentBalance(PriceUtil.toDecimalPrice(currentBalance.longValue()));
            userManagerVO.setSumBalance(PriceUtil.toDecimalPrice(sumBalance.longValue()));
            userManagerVO.setPhone(PhoneUtil.hideBetween(userManagerVO.getPhone()).toString());
        }
        List<Long> userIds = userList.stream().map(UserManagerVO::getUserId).collect(Collectors.toList());

        // 统计用户的订单相关信息
        // eg说明：查询10个用户的订单，但是只有3个用户有下单记录，所以这里只会返回3条数据，
        // 另外的7条记录保持默认值即可，应该在查询用户的时候已经设置了默认值了，所以不需要设置默认值
        QueryOrderDTO queryOrderDTO = new QueryOrderDTO();
        queryOrderDTO.setUserIds(new ArrayList<>(userIds));
        queryOrderDTO.setShopId(AuthUserContext.get().getTenantId());
        ServerResponseEntity<List<UserOrderStatisticVO>> orderResponse = orderFeignClient.countOrderByUserIds(queryOrderDTO);
        if (!Objects.equals(orderResponse.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(orderResponse.getMsg());
        }
        List<UserOrderStatisticVO> data = orderResponse.getData();
        // 组装订单统计数据
        if (CollectionUtils.isNotEmpty(data)) {
            Map<Long, UserOrderStatisticVO> userOrderMap = data.stream().collect(Collectors.toMap(UserOrderStatisticVO::getUserId, (k) -> k));
            assemblyUserData(userList, userOrderMap);
        }
        return userList;
    }

    @Override
    public UserManagerVO getUserInfo(Long userId, Long shopId) {
        PageDTO pageDTO = new PageDTO();
        pageDTO.setPageNum(0);
        pageDTO.setPageSize(1);
        UserManagerDTO userManagerDTO = new UserManagerDTO();
        userManagerDTO.setUserIds(Collections.singletonList(userId));
        PageVO<UserManagerVO> infoPage = getUserInfoPage(pageDTO, userManagerDTO);
        if (infoPage.getTotal() < 1) {
            throw new LuckException("该用户不存在");
        }
        UserManagerVO userManagerVO = infoPage.getList().get(0);
        // 统计用户优惠券相关信息
        ServerResponseEntity<CouponUserCountDataVO> couponUserResponse = couponFeignClient.countCouponUserByUserId(userId, shopId);
        if (!Objects.equals(couponUserResponse.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(couponUserResponse.getMsg());
        }
        userManagerVO.setCouponUserCountDataVO(couponUserResponse.getData());
        return userManagerVO;
    }

    @Override
    public void updateUserLevelByUserExtensionAndUserIds(List<Long> userIds) {
        userMapper.updateUserLevelByUserExtensionAndUserIds(userIds);
    }


    @Override
    @CacheEvict(cacheNames = UserCacheNames.USER_INFO, key = "#userDTO.userId")
    @GlobalTransactional(rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    public void updateUserInfo(UserDTO userDTO) {
        Long userId = userDTO.getUserId();
        Integer status = userDTO.getStatus();
        UserApiVO userApiVO = userMapper.getByUserId(userId);
        boolean isUpdateStatus = Objects.equals(userApiVO.getStatus(), status);
        User user = new User();
        user.setUserId(userDTO.getUserId());
        user.setNickName(userDTO.getNickName());
        if (!isUpdateStatus) {
            user.setStatus(status);
        }
        user.setUpdateTime(DateUtil.date());
        // 更新用户表信息
        this.update(user);
        // 如果用户状态未发生改变，就不需要修改账户表中用户的状态
        if (isUpdateStatus) {
            return;
        }
        // 修改用户状态时需要修改auth_account表的状态,同时需要将用户下线
        AuthAccountDTO authAccountDTO = new AuthAccountDTO();
        authAccountDTO.setUserId(user.getUserId());
        authAccountDTO.setSysType(SysTypeEnum.ORDINARY.value());
        authAccountDTO.setStatus(user.getStatus());
        ServerResponseEntity<Void> updateResponse = accountFeignClient.updateAuthAccountStatusAndDeleteUserToken(authAccountDTO);
        if (!Objects.equals(updateResponse.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(updateResponse.getMsg());
        }
        // 是否开启通联支付，若开启，同步禁用/解禁通联平台的会员
        ServerResponseEntity<String> configResponse = configFeignClient.getConfig(Constant.PAY_SETTLEMENT_CONFIG);
        if (!configResponse.isSuccess()) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
        PaySettlementConfigVO paySettlementConfigVO = Json.parseObject(configResponse.getData(), PaySettlementConfigVO.class);
        if (Objects.equals(PaySysType.ALLINPAY.value(), paySettlementConfigVO.getPaySettlementType())) {
            allinpayFeignClient.updateAllinpayMemberStatus(user.getUserId(), user.getStatus());
        }
    }

    @Override
    public List<UserVO> getUserListByPhones(List<String> phones) {
        if (CollUtil.isEmpty(phones)) {
            return Collections.emptyList();
        }
        return userMapper.getUserListByPhones(phones);
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void batchUser(List<User> userList, List<UserExtension> userExtensionList) {
        if (CollUtil.isEmpty(userList)) {
            return;
        }
        // seata不支持insert into select语句，将语句拆成两步
        // 过滤已存在的用户
        userList = userMapper.filterExistUsers(userList);
        if (CollUtil.isEmpty(userList)) {
            return;
        }
        // 新增用户
        int row = userMapper.saveBatch(userList);
        if (row == 0) {
            return;
        }
        // userList 的大小 不等于 插入row的行数，所以我们要查询插入的用户是那些
        // 如果是已经存在的userId在 userExtensionList中也不要紧，在保存sql的时候会排除掉数据库中已经存在的userId
        List<Long> userIds = userList.stream().map(User::getUserId).collect(Collectors.toList());
        List<UserApiVO> userApiVOList = userMapper.getUserByUserIds(userIds);
        List<Long> dbUserIds = userApiVOList.stream().map(UserApiVO::getUserId).collect(Collectors.toList());
        userExtensionList = userExtensionList.stream().filter(item -> dbUserIds.contains(item.getUserId())).collect(Collectors.toList());
        // 过滤已存在的userExtension
        userExtensionList = userExtensionService.filterExistExtensions(userExtensionList);
        if (CollUtil.isNotEmpty(userExtensionList)) {
            userExtensionService.saveBatch(userExtensionList);
            // 积分、成长值、余额日志
            userExtensionService.registerUserScoreGrowthBalanceLog(userExtensionList);
            // 赠送注册积分
            userLevelService.registerUserScore(userExtensionList);
            // 导入后赠送等级相关的积分和权益
            userLevelService.registerUserSendRights(userExtensionList);
        }
        // 是否开启通联支付，若开启则注册通联平台的个人会员
        String data = configFeignClient.getConfig(Constant.PAY_SETTLEMENT_CONFIG).getData();
        if (!ObjectUtils.isEmpty(data)) {
            PaySettlementConfig config = JSON.parseObject(data, PaySettlementConfig.class);
            if (config.getPaySettlementType() != null && config.getPaySettlementType() == 1) {
                List<String> bizUserIds = userIds.stream().map(Object::toString).collect(Collectors.toList());
                allinpayFeignClient.batchCreatePersonalMember(bizUserIds);
            }
        }
    }

    @Override
    public List<UserVO> getUserByCreateTimeRange(Integer status, Date startDate, Date endDate) {
        return userMapper.getUserByCreateTimeRange(status, startDate, endDate);
    }

    @Override
    public MemberOverviewVO getUserCountInfo(Date endTime) {
        Date startTime = DateUtil.beginOfDay(endTime);
        return userMapper.getUserCountInfo(startTime, endTime);
    }

    @Override
    public List<UserApiVO> listUserByMobile(String mobile) {
        return userMapper.listUserByMobile(mobile);
    }

    @Override
    public Integer countUserByLevel(Integer level, Integer levelType) {
        return userMapper.countUserByLevel(level, levelType);
    }

    @Override
    public List<UserVO> selectMemberByEndTime(DateTime endOfDay) {
        return userMapper.selectMemberByEndTime(endOfDay);
    }

    @Override
    public void updateUserTypeLevelByUserExtensionAndUserIds(List<Long> userIds) {
        userMapper.updateUserTypeLevelByUserExtensionAndUserIds(userIds);
    }


    private void assemblyUserData(List<UserManagerVO> userList, Map<Long, UserOrderStatisticVO> userOrderMap) {
        for (UserManagerVO userManagerVO : userList) {
            UserOrderStatisticVO orderStatisticVO = userOrderMap.get(userManagerVO.getUserId());
            if (Objects.isNull(orderStatisticVO)) {
                userManagerVO.setActualAmount(new BigDecimal(0));
                userManagerVO.setConsAmount(new BigDecimal(0));
                userManagerVO.setConsTimes(0);
                userManagerVO.setAfterSaleAmount(new BigDecimal(0));
                userManagerVO.setAfterSaleTimes(0);
                userManagerVO.setAllCount(0);
                continue;
            }
            BigDecimal rechargeAmount = Objects.nonNull(userManagerVO.getRechargeAmount()) ? userManagerVO.getRechargeAmount() : new BigDecimal(0);
            // 实付金额 累计支付的金额: 除了余额支付/积分支付的订单累计金额 + 余额充值金额
            userManagerVO.setActualAmount(PriceUtil.toDecimalPrice(orderStatisticVO.getActualAmount().longValue()).add(rechargeAmount));
            // 最近支付下单时间
            Date reConsTime1 = orderStatisticVO.getReConsTime();
            // 最近余额充值时间
            Date reConsTime2 = userManagerVO.getReConsTime();
            // 最近消费时间 reConsTime1 reConsTime2 比较
            if (Objects.isNull(reConsTime2)) {
                userManagerVO.setReConsTime(reConsTime1);
            } else if (Objects.nonNull(reConsTime1)) {
                userManagerVO.setReConsTime(DateUtil.compare(reConsTime1, reConsTime2) >= 0 ? reConsTime1 : reConsTime2);
            }
            userManagerVO.setConsAmount(PriceUtil.toDecimalPrice(orderStatisticVO.getConsAmount().longValue()));
            userManagerVO.setConsTimes(orderStatisticVO.getConsTimes());
            userManagerVO.setAverDiscount(orderStatisticVO.getAverDiscount());
            userManagerVO.setAfterSaleAmount(PriceUtil.toDecimalPrice(orderStatisticVO.getAfterSaleAmount().longValue()));
            userManagerVO.setAfterSaleTimes(orderStatisticVO.getAfterSaleTimes());
            userManagerVO.setAllCount(orderStatisticVO.getAllCount());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void destroyUser(Long userId) {

        userMapper.deleteById(userId);
        userAddrService.deleteUserAddrByUserId(null, userId);
        UserExtension userExtension = userExtensionService.getByUserId(userId);
        userExtensionService.deleteById(userExtension.getUserExtensionId());
        userConsigneeService.deleteByUserId(userId);
        userGrowthLogService.deleteByUserId(userId);
        userScoreGetLogService.deleteByUserId(userId);
        userScoreLockService.deleteByUserId(userId);
        userScoreLogService.deleteByUserId(userId);
        userTagUserService.deleteByUserId(userId);
        accountFeignClient.deleteByUserIdAndSysType(userId);
        tokenFeignClient.clearToken();
        RedisUtil.del(UserCacheNames.USER_INFO + UserCacheNames.UNION + userId);
    }

    @Override
    public List<UserApiVO> getUserByParam(UserApiVO userApiVO) {
        return userMapper.getUserByParam(userApiVO);
    }

    @Override
    public PageVO<UserManagerVO> pageShopCustomerByParam(PageDTO pageDTO, ShopCustomerDTO shopCustomerDTO) {
        List<UserManagerVO> users = shopCustomerService.listByParam(shopCustomerDTO);
        if (CollUtil.isEmpty(users)) {
            return new PageVO<>();
        }
        List<Long> userIdList = users.stream().map(UserManagerVO::getUserId).collect(Collectors.toList());
        QueryOrderDTO queryOrderDTO = new QueryOrderDTO();
        queryOrderDTO.setUserIds(userIdList);
        queryOrderDTO.setShopId(shopCustomerDTO.getShopId());
        ServerResponseEntity<List<UserOrderStatisticVO>> orderResponse = orderFeignClient.countOrderByUserIds(queryOrderDTO);
        if (!Objects.equals(orderResponse.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(orderResponse.getMsg());
        }
        List<UserOrderStatisticVO> orderData = orderResponse.getData();

        Map<Long, UserOrderStatisticVO> orderDataMap = orderData.stream().collect(Collectors.toMap(UserOrderStatisticVO::getUserId, (u) -> u));
        for (UserManagerVO userManagerVO : users) {
            UserOrderStatisticVO userOrderData = orderDataMap.get(userManagerVO.getUserId());
            userManagerVO.setReConsTime(Objects.nonNull(userOrderData) ? userOrderData.getReConsTime() : null);
            userManagerVO.setConsTimes(Objects.nonNull(userOrderData) ? userOrderData.getConsTimes() : 0);
            userManagerVO.setAllCount(Objects.nonNull(userOrderData) ? userOrderData.getAllCount() : 0);
            userManagerVO.setAverDiscount(Objects.nonNull(userOrderData) ? userOrderData.getAverDiscount() : new BigDecimal(0));
            userManagerVO.setConsAmount(Objects.nonNull(userOrderData) ? PriceUtil.toDecimalPrice(userOrderData.getConsAmount().longValue()) : new BigDecimal(0));
            userManagerVO.setAfterSaleAmount(Objects.nonNull(userOrderData) ? PriceUtil.toDecimalPrice(userOrderData.getAfterSaleAmount().longValue()) : new BigDecimal(0));
            userManagerVO.setActualAmount(Objects.nonNull(userOrderData) ? PriceUtil.toDecimalPrice(userOrderData.getActualAmount().longValue()) : new BigDecimal(0));
            userManagerVO.setAfterSaleTimes(Objects.nonNull(userOrderData) ? userOrderData.getAfterSaleTimes() : 0);
            userManagerVO.setPhone(PhoneUtil.hideBetween(userManagerVO.getPhone()).toString());

        }
        Integer sort = shopCustomerDTO.getSort();
        if (Objects.equals(shopCustomerDTO.getSort(), OrderSortEnum.ALL_COUNT_ASC.value())) {
            users.sort(Comparator.comparing(UserManagerVO::getAllCount));
        } else if (Objects.equals(sort, OrderSortEnum.ALL_COUNTC_DESC.value())) {
            users.sort(Comparator.comparing(UserManagerVO::getAllCount).reversed());
        } else if (Objects.equals(sort, OrderSortEnum.AVER_DISCOUNT_ASC.value())) {
            users.sort(Comparator.comparing(UserManagerVO::getAverDiscount));
        } else if (Objects.equals(sort, OrderSortEnum.AVER_DISCOUNT_DESC.value())) {
            users.sort(Comparator.comparing(UserManagerVO::getAverDiscount).reversed());
        } else if (Objects.equals(sort, OrderSortEnum.AFTER_SALE_TIMES_ASC.value())) {
            users.sort(Comparator.comparing(UserManagerVO::getAfterSaleTimes));
        } else if (Objects.equals(sort, OrderSortEnum.AFTER_SALE_TIMES_DESC.value())) {
            users.sort(Comparator.comparing(UserManagerVO::getAfterSaleTimes).reversed());
        } else if (Objects.equals(sort, OrderSortEnum.AFTER_SALE_AMOUNT_ASC.value())) {
            users.sort(Comparator.comparing(UserManagerVO::getAfterSaleAmount));
        } else if (Objects.equals(sort, OrderSortEnum.AFTER_SALE_AMOUNT_DESC.value())) {
            users.sort(Comparator.comparing(UserManagerVO::getAfterSaleAmount).reversed());
        } else if (Objects.equals(sort, OrderSortEnum.CONS_AMOUNT_ASC.value())) {
            users.sort(Comparator.comparing(UserManagerVO::getConsAmount));
        } else if (Objects.equals(sort, OrderSortEnum.CONS_AMOUNT_DESC.value())) {
            users.sort(Comparator.comparing(UserManagerVO::getConsAmount).reversed());
        } else if (Objects.equals(sort, OrderSortEnum.ACTUAL_AMOUNT_ASC.value())) {
            users.sort(Comparator.comparing(UserManagerVO::getActualAmount));
        } else if (Objects.equals(sort, OrderSortEnum.ACTUAL_AMOUNT_DESC.value())) {
            users.sort(Comparator.comparing(UserManagerVO::getActualAmount).reversed());
        } else if (Objects.equals(sort, OrderSortEnum.CONS_TIMES_ASC.value())) {
            users.sort(Comparator.comparing(UserManagerVO::getConsTimes));
        } else if (Objects.equals(sort, OrderSortEnum.CONS_TIMES_DESC.value())) {
            users.sort(Comparator.comparing(UserManagerVO::getConsTimes).reversed());
        }
        PageVO<UserManagerVO> pageVO = new PageVO<>();
        List<UserManagerVO> result = users.stream().skip((long) (pageDTO.getPageNum() - 1) * pageDTO.getPageSize()).limit(pageDTO.getPageSize()).collect(Collectors.toList());
        pageVO.setTotal((long) users.size());
        pageVO.setPages((users.size() - 1) / pageDTO.getPageSize() + 1);
        pageVO.setList(result);
        return pageVO;
    }

    @Override
    public List<User> listUser(UserManagerDTO userManagerDTO) {
        return userMapper.listUser(userManagerDTO);
    }

    @Override
    public void updateUserInfoByAllinpay() {
        List<User> users = userMapper.listUser(null);
        if (CollUtil.isEmpty(users)) {
            return;
        }
        List<Long> userIds = users.stream().map(User::getUserId).collect(Collectors.toList());
        // 循环更新用户通联信息
        UserExtension userExtension;
        PersonalMemberInfo memberInfo;
        Boolean isBindPayAcct;
        for (Long userId : userIds) {
            userExtension = userExtensionService.getByUserId(userId);
            // 查询个人会员信息
            memberInfo = allinpayFeignClient.getPersonalMemberInfo(userId.toString()).getData();
            if (memberInfo != null) {
                userExtension.setAllinpayRealNameSet(memberInfo.getIdentityChecked() ? 1 : 0);
                userExtension.setAllinpayPhoneBind(memberInfo.getPhoneChecked() ? 1 : 0);
                userExtension.setAllinpayPayPwdSet(memberInfo.getSetPayPwd() ? 1 : 0);
                userExtension.setAllinpayProtocolSign(memberInfo.getSignAcctProtocolTime() != null ? 1 : 0);
            }
            isBindPayAcct = allinpayFeignClient.isBindPayAcct(userId).getData();
            userExtension.setAllinpayPayAcctBind(isBindPayAcct ? 1 : 0);
            // 更新用户通联信息
            userExtensionService.update(userExtension);
        }
    }

    @Override
    public Integer countNewUserByTime(Date startTime, Date endTime) {
        if (Objects.isNull(startTime) && Objects.isNull(endTime)) {
            return 0;
        }
        return userMapper.countNewUserByTime(startTime, endTime);
    }

    @Override
    public List<Long> listNewUserIdByTime(Date startTime, Date endTime) {
        if (Objects.isNull(startTime) && Objects.isNull(endTime)) {
            return new ArrayList<>(0);
        }
        return userMapper.listNewUserIdByTime(startTime, endTime);
    }

    @Override
    public List<UserVO> listUserByUserIds(List<Long> userIds) {
        if (CollUtil.isEmpty(userIds)) {
            return Collections.emptyList();
        }
        return userMapper.listUserByUserIds(userIds);
    }
}
