package com.dora.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.dora.dto.AuthDto;
import com.dora.entity.Order;
import com.dora.entity.PointsPackage;
import com.dora.entity.User;
import com.dora.mapper.OrderMapper;
import com.dora.mapper.PointsPackageMapper;
import com.dora.mapper.UserMapper;
import com.dora.service.JwtTokenManager;
import com.dora.service.MsmService;
import com.dora.service.PromotionCommissionService;
import com.dora.service.UserMembershipService;
import com.dora.service.UserService;
import com.dora.util.JwtUtil;
import com.dora.util.PromotionLevelCalculator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import com.dora.util.MembershipUtil;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;

/**
 * 用户服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;
    private final OrderMapper orderMapper;
    private final PointsPackageMapper pointsPackageMapper;
    private final MsmService msmService;
    private final JwtUtil jwtUtil;
    private final RedisTemplate<String, String> redisTemplate;
    private final UserMembershipService userMembershipService;
    private final PromotionCommissionService promotionCommissionService;
    private final MembershipUtil membershipUtil;
    private final PromotionLevelCalculator promotionLevelCalculator;
    private final JwtTokenManager jwtTokenManager;
    private final com.dora.service.PointsService pointsService;

    // 默认头像URL
    private static final String DEFAULT_AVATAR_URL = "https://img.remit.ee/api/file/BQACAgUAAyEGAASHRsPbAAJblmiMe_d10FU66N4nQAQMfscumNdFAALDGwACUsZhVEphmi-3nWulNgQ.png";

    @Override
    public AuthDto.LoginResponse smsLogin(String phone, String code) {
        // 1. 验证短信验证码
        String cachedCode = redisTemplate.opsForValue().get(phone);
        if (!StringUtils.hasText(cachedCode)) {
            throw new RuntimeException("验证码错误或已过期");
        }
        
        if (!cachedCode.equals(code)) {
            // 验证码错误时清除Redis中的验证码，防止重复使用错误验证码
            redisTemplate.delete(phone);
            log.warn("验证码错误，已清除缓存的验证码 - phone: {}", phone);
            throw new RuntimeException("验证码错误或已过期");
        }

        // 2. 查找用户（包含禁用用户）
        User user = userMapper.selectByPhoneAnyStatus(phone);
        if (user == null) {
            // 用户不存在时也要清除验证码，一个验证码只能用于一次验证操作
            redisTemplate.delete(phone);
            log.warn("用户不存在，已清除缓存的验证码 - phone: {}", phone);
            throw new RuntimeException("用户不存在，请先注册");
        }

        // 2.1 禁用账号拦截
        if (user.getIsDeleted() != null && user.getIsDeleted() == 1) {
            redisTemplate.delete(phone);
            log.warn("用户已被禁用，短信登录拦截 - phone: {}", phone);
            throw new RuntimeException("该账号已被管理员禁用，如有疑问请联系客服");
        }

        // 3. 生成JWT令牌
        String token = jwtUtil.generateToken(user.getId(), user.getPhone());

        // 4. 将token添加到管理器中（实现设备数限制）
        String jwtId = jwtUtil.getJwtIdFromToken(token);
        jwtTokenManager.addUserToken(user.getId(), jwtId, System.currentTimeMillis());

        // 5. 删除Redis中的验证码
        redisTemplate.delete(phone);

        // 6. 构建响应
        AuthDto.LoginResponse response = new AuthDto.LoginResponse();
        response.setToken(token);
        response.setTokenExpiresAt(formatTokenExpirationTime(jwtUtil.getTokenExpirationTime()));
        response.setUserInfo(convertToUserInfoResponse(user));

        log.info("用户短信登录成功 - phone: {}, userId: {}", phone, user.getId());
        return response;
    }

    @Override
    public AuthDto.LoginResponse passwordLogin(String phone, String password) {
        // 1. 查找用户（包含禁用用户）
        User user = userMapper.selectByPhoneAnyStatus(phone);
        if (user == null) {
            throw new RuntimeException("用户不存在，请先注册");
        }

        // 1.1 禁用账号拦截
        if (user.getIsDeleted() != null && user.getIsDeleted() == 1) {
            log.warn("用户已被禁用，密码登录拦截 - phone: {}", phone);
            throw new RuntimeException("该账号已被管理员禁用，如有疑问请联系客服");
        }

        // 2. 验证密码
        if (!StringUtils.hasText(user.getPasswordJwt()) || 
            !user.getPasswordJwt().equals(password)) {
            throw new RuntimeException("手机号或密码错误");
        }

        // 3. 生成JWT令牌
        String token = jwtUtil.generateToken(user.getId(), user.getPhone());

        // 4. 将token添加到管理器中（实现设备数限制）
        String jwtId = jwtUtil.getJwtIdFromToken(token);
        jwtTokenManager.addUserToken(user.getId(), jwtId, System.currentTimeMillis());

        // 5. 构建响应
        AuthDto.LoginResponse response = new AuthDto.LoginResponse();
        response.setToken(token);
        response.setTokenExpiresAt(formatTokenExpirationTime(jwtUtil.getTokenExpirationTime()));
        response.setUserInfo(convertToUserInfoResponse(user));

        log.info("用户密码登录成功 - phone: {}, userId: {}", phone, user.getId());
        return response;
    }

    @Override
    public AuthDto.LoginResponse register(String phone, String code, String password, String inviteCode) {
        // 1. 验证短信验证码
        String cachedCode = redisTemplate.opsForValue().get(phone);
        if (!StringUtils.hasText(cachedCode)) {
            throw new RuntimeException("验证码错误或已过期");
        }
        
        if (!cachedCode.equals(code)) {
            // 验证码错误时清除Redis中的验证码，防止重复使用错误验证码
            redisTemplate.delete(phone);
            log.warn("注册验证码错误，已清除缓存的验证码 - phone: {}", phone);
            throw new RuntimeException("验证码错误或已过期");
        }

        // 2. 检查手机号是否已注册（包含禁用用户）
        User existingUser = userMapper.selectByPhoneAnyStatus(phone);
        if (existingUser != null) {
            // 手机号已存在时清除验证码，防止重复使用
            redisTemplate.delete(phone);
            if (existingUser.getIsDeleted() != null && existingUser.getIsDeleted() == 1) {
                log.warn("手机号对应账号已被禁用，注册拦截 - phone: {}", phone);
                throw new RuntimeException("该账号已被管理员禁用，如有疑问请联系客服");
            }
            log.warn("手机号已注册，已清除缓存的验证码 - phone: {}", phone);
            throw new RuntimeException("该手机号已注册");
        }

        // 3. 验证密码（如果提供了密码）
        if (StringUtils.hasText(password) && (password.length() < 6 || password.length() > 20)) {
            // 密码格式错误时清除验证码，防止重复使用
            redisTemplate.delete(phone);
            log.warn("密码长度不符合要求，已清除缓存的验证码 - phone: {}", phone);
            throw new RuntimeException("密码长度必须在6-20位之间");
        }

        // 3. 处理邀请码（这里先验证，实际建立关系在用户创建后）
        Long inviterId = null;
        if (StringUtils.hasText(inviteCode)) {
            User inviter = userMapper.selectByInviteCode(inviteCode);
            if (inviter == null) {
                // 邀请码无效时清除验证码，防止重复使用
                redisTemplate.delete(phone);
                log.warn("邀请码无效，已清除缓存的验证码 - phone: {}, inviteCode: {}", phone, inviteCode);
                throw new RuntimeException("邀请码无效");
            }
            inviterId = inviter.getId();
        }

        // 4. 生成随机用户名
        String username = generateRandomUsername();

        // 5. 生成基于时间戳的用户ID
        Long userId = generateUserId();

        // 6. 创建新用户
        User newUser = new User();
        newUser.setId(userId); // 设置自定义用户ID
        newUser.setPhone(phone);
        newUser.setUsername(username);
        // 仅当密码不为空时设置密码
        if (StringUtils.hasText(password)) {
            newUser.setPasswordJwt(password); // 存储密码
        }
        newUser.setRole(1); // 先设置为普通用户，注册成功后再设置为VIP
        newUser.setMembershipExpiresAt(LocalDateTime.now().plusDays(2)); // 设置2天后过期
        newUser.setAvatarUrl(DEFAULT_AVATAR_URL); // 设置默认头像
        newUser.setIsVerified(0); // 未实名认证
        newUser.setInviteCode(generateInviteCode());
        newUser.setInviterId(inviterId);
        newUser.setPromotionLevel(1); // 新用户默认为1级推广等级
        newUser.setPoints(0);
        newUser.setPointsExpiresAt(null);
        newUser.setCreateTime(LocalDateTime.now());
        newUser.setUpdateTime(LocalDateTime.now());
        newUser.setIsDeleted(0);

        // 7. 保存用户
        int result = userMapper.insert(newUser);
        if (result <= 0) {
            throw new RuntimeException("用户注册失败");
        }

        // 8. 设置默认VIP身份
        userMembershipService.setDefaultVipForNewUser(userId);

        // 9. 处理推广关系和推广等级更新（统一在注册时处理）
        if (StringUtils.hasText(inviteCode)) {
            try {
                // 9.1 建立推广关系
                boolean success = promotionCommissionService.establishPromotionRelationship(userId, inviteCode);
                if (success) {
                    log.info("推广关系建立成功 - newUserId: {}, inviteCode: {}", userId, inviteCode);
                    
                    // 9.2 获取邀请人信息并更新其推广等级
                    User inviter = userMapper.selectByInviteCode(inviteCode);
                    if (inviter != null) {
                        // 使用之前已定义的inviterId变量
                        inviterId = inviter.getId();
                        boolean inviterLevelUpdated = promotionLevelCalculator.updateUserPromotionLevelOnRegistration(inviterId);
                        if (inviterLevelUpdated) {
                            log.info("邀请人推广等级更新成功 - inviterId: {}, newUserId: {}", inviterId, userId);
                        } else {
                            log.warn("邀请人推广等级更新失败，但不影响注册流程 - inviterId: {}, newUserId: {}", inviterId, userId);
                        }
                    }
                } else {
                    log.warn("推广关系建立失败 - newUserId: {}, inviteCode: {}", userId, inviteCode);
                }
            } catch (Exception e) {
                log.error("推广关系建立异常，但不影响注册流程 - newUserId: {}, inviteCode: {}", userId, inviteCode, e);
            }
        }
        
        // 10. 发放新用户注册奖励积分
        try {
            pointsService.grantPoints(userId, 200, "新用户注册奖励");
            log.info("新用户注册积分发放成功 - userId: {}, 积分: 200", userId);
            
            // 10.1 如果有邀请人，发放邀请奖励积分
            if (inviterId != null) {
                pointsService.grantPoints(inviterId, 500, "邀请新用户注册奖励");
                log.info("邀请人奖励积分发放成功 - inviterId: {}, 积分: 500, newUserId: {}", inviterId, userId);
            }
        } catch (Exception e) {
            log.error("注册积分发放异常，但不影响注册流程 - userId: {}, inviterId: {}", userId, inviterId, e);
        }
        
        // 11. 更新新用户自己的推广等级（基于总粉丝数，新用户通常为0粉丝，等级为1）
        try {
            boolean newUserLevelUpdated = promotionLevelCalculator.updateUserPromotionLevelOnRegistration(userId);
            if (newUserLevelUpdated) {
                log.info("新用户推广等级初始化完成 - userId: {}", userId);
            } else {
                log.warn("新用户推广等级初始化失败，但不影响注册流程 - userId: {}", userId);
            }
        } catch (Exception e) {
            log.error("新用户推广等级初始化异常，但不影响注册流程 - userId: {}", userId, e);
        }

        // 12. 生成JWT令牌
        String token = jwtUtil.generateToken(newUser.getId(), newUser.getPhone());
        
        // 12.1 将token添加到管理器中（实现设备数限制）
        String jwtId = jwtUtil.getJwtIdFromToken(token);
        jwtTokenManager.addUserToken(newUser.getId(), jwtId, System.currentTimeMillis());

        // 13. 删除Redis中的验证码
        redisTemplate.delete(phone);

        // 14. 重新获取用户信息（包含VIP状态和最新积分）
        User updatedUser = userMapper.selectById(userId);

        // 15. 构建响应
        AuthDto.LoginResponse response = new AuthDto.LoginResponse();
        response.setToken(token);
        response.setTokenExpiresAt(formatTokenExpirationTime(jwtUtil.getTokenExpirationTime()));
        response.setUserInfo(convertToUserInfoResponse(updatedUser));

        log.info("用户注册成功 - phone: {}, userId: {}, username: {}", phone, userId, username);
        return response;
    }

    @Override
    public User getUserById(Long userId) {
        return userMapper.selectById(userId);
    }

    @Override
    public User getUserByPhone(String phone) {
        return userMapper.selectByPhone(phone);
    }

    @Override
    public User getUserByUsername(String username) {
        return userMapper.selectByUsername(username);
    }

    @Override
    public AuthDto.UserInfoResponse getCurrentUserInfo(Long userId) {
        User user = getUserById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        return convertToUserInfoResponse(user);
    }

    @Override
    public boolean updateProfile(Long userId, String username, String avatarUrl) {
        User user = getUserById(userId);
        if (user == null) {
            return false;
        }

        // 检查用户名是否可用（如果提供了新用户名且与当前用户名不同）
        if (StringUtils.hasText(username) && !username.equals(user.getUsername())) {
            if (!isUsernameAvailable(username)) {
                throw new RuntimeException("用户名已被使用");
            }
            user.setUsername(username);
        }

        // 更新头像
        if (StringUtils.hasText(avatarUrl)) {
            user.setAvatarUrl(avatarUrl);
        }
        
        user.setUpdateTime(LocalDateTime.now());

        return userMapper.updateById(user) > 0;
    }

    @Override
    public boolean updateUsername(Long userId, String newUsername) {
        // 检查用户名是否可用
        if (!isUsernameAvailable(newUsername)) {
            throw new RuntimeException("用户名已被使用");
        }

        User user = getUserById(userId);
        if (user == null) {
            return false;
        }

        user.setUsername(newUsername);
        user.setUpdateTime(LocalDateTime.now());

        return userMapper.updateById(user) > 0;
    }

    @Override
    public boolean resetPassword(String phone, String code, String newPassword) {
        // 1. 验证短信验证码
        String cachedCode = redisTemplate.opsForValue().get(phone);
        if (!StringUtils.hasText(cachedCode)) {
            throw new RuntimeException("验证码错误或已过期");
        }
        
        if (!cachedCode.equals(code)) {
            // 验证码错误时清除Redis中的验证码，防止重复使用错误验证码
            redisTemplate.delete(phone);
            log.warn("重置密码验证码错误，已清除缓存的验证码 - phone: {}", phone);
            throw new RuntimeException("验证码错误或已过期");
        }

        // 2. 查找用户
        User user = userMapper.selectByPhone(phone);
        if (user == null) {
            // 用户不存在时清除验证码，防止重复使用
            redisTemplate.delete(phone);
            log.warn("重置密码时用户不存在，已清除缓存的验证码 - phone: {}", phone);
            throw new RuntimeException("用户不存在");
        }

        // 3. 更新密码
        user.setPasswordJwt(newPassword);
        user.setUpdateTime(LocalDateTime.now());

        boolean success = userMapper.updateById(user) > 0;
        
        // 4. 删除Redis中的验证码
        if (success) {
            redisTemplate.delete(phone);
            log.info("用户密码重置成功 - phone: {}, userId: {}", phone, user.getId());
        }

        return success;
    }

    @Override
    public boolean isUsernameAvailable(String username) {
        User existingUser = userMapper.selectByUsername(username);
        return existingUser == null;
    }

    @Override
    public String generateInviteCode() {
        // 生成6位随机字母数字组合
        return RandomUtil.randomString(6).toUpperCase();
    }

    @Override
    public boolean updateVerificationStatus(Long userId, Integer isVerified) {
        return userMapper.updateVerificationStatus(userId, isVerified) > 0;
    }

    @Override
    public boolean updateRealIdentity(Long userId, String realUsername, String idNumber) {
        try {
            // 检查用户是否存在
            User user = userMapper.selectById(userId);
            if (user == null) {
                throw new RuntimeException("用户不存在");
            }

            // 更新真实身份信息
            user.setRealUsername(realUsername);
            user.setIdNumber(idNumber);
            user.setUpdateTime(LocalDateTime.now());

            boolean success = userMapper.updateById(user) > 0;
            
            if (success) {
                log.info("用户真实身份信息更新成功 - userId: {}, realUsername: {}", userId, realUsername);
            }

            return success;
        } catch (Exception e) {
            log.error("更新用户真实身份信息失败 - userId: {}", userId, e);
            throw new RuntimeException("更新真实身份信息失败: " + e.getMessage());
        }
    }

    @Override
    public AuthDto.RealIdentityResponse getRealIdentity(Long userId) {
        try {
            User user = userMapper.selectById(userId);
            if (user == null) {
                throw new RuntimeException("用户不存在");
            }

            AuthDto.RealIdentityResponse response = new AuthDto.RealIdentityResponse();
            response.setRealUsername(user.getRealUsername());
            response.setIdNumber(user.getIdNumber());
            response.setIsVerified(user.getIsVerified());

            return response;
        } catch (Exception e) {
            log.error("获取用户真实身份信息失败 - userId: {}", userId, e);
            throw new RuntimeException("获取真实身份信息失败: " + e.getMessage());
        }
    }

    @Override
    public boolean updatePhone(Long userId, String newPhone, String code) {
        try {
            // 1. 验证短信验证码
            String cachedCode = redisTemplate.opsForValue().get(newPhone);
            if (!StringUtils.hasText(cachedCode)) {
                throw new RuntimeException("验证码错误或已过期");
            }
            
            if (!cachedCode.equals(code)) {
                // 验证码错误时清除Redis中的验证码，防止重复使用错误验证码
                redisTemplate.delete(newPhone);
                log.warn("更新手机号验证码错误，已清除缓存的验证码 - newPhone: {}", newPhone);
                throw new RuntimeException("验证码错误或已过期");
            }

            // 2. 检查用户是否存在
            User user = userMapper.selectById(userId);
            if (user == null) {
                // 用户不存在时清除验证码，防止重复使用
                redisTemplate.delete(newPhone);
                log.warn("更新手机号时用户不存在，已清除缓存的验证码 - userId: {}, newPhone: {}", userId, newPhone);
                throw new RuntimeException("用户不存在");
            }

            // 3. 检查新手机号是否已被其他用户使用
            User existingUser = userMapper.selectByPhone(newPhone);
            if (existingUser != null && !existingUser.getId().equals(userId)) {
                // 新手机号已被使用时清除验证码，防止重复使用
                redisTemplate.delete(newPhone);
                log.warn("手机号已被其他用户使用，已清除缓存的验证码 - newPhone: {}", newPhone);
                throw new RuntimeException("手机号已被其他用户使用");
            }

            // 4. 更新手机号
            user.setPhone(newPhone);
            user.setUpdateTime(LocalDateTime.now());

            boolean success = userMapper.updateById(user) > 0;
            
            // 5. 删除Redis中的验证码
            if (success) {
                redisTemplate.delete(newPhone);
                log.info("用户手机号更新成功 - userId: {}, newPhone: {}", userId, newPhone);
            }

            return success;
        } catch (Exception e) {
            log.error("更新用户手机号失败 - userId: {}, newPhone: {}", userId, newPhone, e);
            throw new RuntimeException("更新手机号失败: " + e.getMessage());
        }
    }

    @Override
    public boolean updatePasswordWithCode(String phone, String code, String newPassword) {
        try {
            // 1. 验证短信验证码
            String cachedCode = redisTemplate.opsForValue().get(phone);
            if (!StringUtils.hasText(cachedCode)) {
                throw new RuntimeException("验证码错误或已过期");
            }
            
            if (!cachedCode.equals(code)) {
                // 验证码错误时清除Redis中的验证码，防止重复使用错误验证码
                redisTemplate.delete(phone);
                log.warn("修改密码验证码错误，已清除缓存的验证码 - phone: {}", phone);
                throw new RuntimeException("验证码错误或已过期");
            }

            // 2. 查找用户
            User user = userMapper.selectByPhone(phone);
            if (user == null) {
                // 用户不存在时清除验证码，防止重复使用
                redisTemplate.delete(phone);
                log.warn("修改密码时用户不存在，已清除缓存的验证码 - phone: {}", phone);
                throw new RuntimeException("用户不存在");
            }

            // 3. 更新密码
            user.setPasswordJwt(newPassword);
            user.setUpdateTime(LocalDateTime.now());

            boolean success = userMapper.updateById(user) > 0;
            
            // 4. 删除Redis中的验证码
            if (success) {
                redisTemplate.delete(phone);
                log.info("用户密码修改成功 - phone: {}, userId: {}", phone, user.getId());
            }

            return success;
        } catch (Exception e) {
            log.error("修改密码失败 - phone: {}", phone, e);
            throw new RuntimeException("修改密码失败: " + e.getMessage());
        }
    }

    @Override
    public boolean verifyCurrentPassword(Long userId, String password) {
        try {
            // 1. 检查用户是否存在
            User user = userMapper.selectById(userId);
            if (user == null) {
                throw new RuntimeException("用户不存在");
            }

            // 2. 验证密码
            if (!StringUtils.hasText(user.getPasswordJwt()) || 
                !user.getPasswordJwt().equals(password)) {
                log.warn("用户密码验证失败 - userId: {}", userId);
                return false;
            }

            log.info("用户密码验证成功 - userId: {}", userId);
            return true;
        } catch (Exception e) {
            log.error("验证用户密码失败 - userId: {}", userId, e);
            throw new RuntimeException("验证密码失败: " + e.getMessage());
        }
    }

    /**
     * 生成随机中文用户名
     */
    private String generateRandomUsername() {
        // 常用中文字符
        String[] chineseChars = {
            "用户"
        };
        
        // 随机选择一个中文前缀
        String prefix = chineseChars[RandomUtil.randomInt(chineseChars.length)];
        
        // 生成6位随机数字
        String suffix = String.valueOf(RandomUtil.randomInt(100000, 999999));
        
        return prefix + suffix;
    }

    /**
     * 生成基于时间戳的用户ID
     * 格式：当前时间戳 + 随机数（确保唯一性）
     */
    private Long generateUserId() {
        long timestamp = System.currentTimeMillis();
        int random = RandomUtil.randomInt(1000, 9999);
        return timestamp * 10000 + random;
    }

    @Override
    public User getUserByWechatOpenid(String wechatOpenid) {
        try {
            if (!StringUtils.hasText(wechatOpenid)) {
                throw new RuntimeException("微信openid不能为空");
            }
            
            // 查询包含禁用用户
            User user = userMapper.selectByWechatOpenidAnyStatus(wechatOpenid);
            log.info("根据微信openid查询用户 - openid: {}, 结果: {}", wechatOpenid, user != null ? "找到用户" : "用户不存在");
            return user;
        } catch (Exception e) {
            log.error("根据微信openid查询用户失败 - openid: {}", wechatOpenid, e);
            throw new RuntimeException("查询用户失败: " + e.getMessage());
        }
    }

    @Override
    public User getUserByInviteCode(String inviteCode) {
        try {
            if (!StringUtils.hasText(inviteCode)) {
                return null;
            }
            
            User user = userMapper.selectByInviteCode(inviteCode);
            log.info("根据推广码查询用户 - inviteCode: {}, 结果: {}", inviteCode, user != null ? "找到用户" : "用户不存在");
            return user;
        } catch (Exception e) {
            log.error("根据推广码查询用户失败 - inviteCode: {}", inviteCode, e);
            throw new RuntimeException("查询用户失败: " + e.getMessage());
        }
    }

    @Override
    public AuthDto.LoginResponse wechatLogin(String wechatOpenid, String sceneStr) {
        try {
            if (!StringUtils.hasText(wechatOpenid)) {
                throw new RuntimeException("微信openid不能为空");
            }

            // 1. 根据微信openid查找用户（包含禁用用户）
            User user = getUserByWechatOpenid(wechatOpenid);
            
            if (user == null) {
                // 2. 用户不存在，创建新用户（传入场景值以获取推广码）
                user = createWechatUser(wechatOpenid, sceneStr);
                log.info("微信登录创建新用户成功 - openid: {}, userId: {}, sceneStr: {}", 
                        wechatOpenid, user.getId(), sceneStr);
            } else {
                // 1.1 禁用账号拦截
                if (user.getIsDeleted() != null && user.getIsDeleted() == 1) {
                    log.warn("用户已被禁用，微信登录拦截 - openid: {}, userId: {}", wechatOpenid, user.getId());
                    throw new RuntimeException("该账号已被管理员禁用，如有疑问请联系客服");
                }

                log.info("微信登录用户已存在 - openid: {}, userId: {}", wechatOpenid, user.getId());
                // 如果是已存在用户，清理可能的推广码缓存
                if (StringUtils.hasText(sceneStr)) {
                    String inviteKey = "wx_login_scene:" + sceneStr + ":invite";
                    redisTemplate.delete(inviteKey);
                }
            }

            // 3. 生成JWT令牌
            String token = jwtUtil.generateToken(user.getId(), user.getPhone());

            // 4. 将token添加到管理器中（实现设备数限制）
            String jwtId = jwtUtil.getJwtIdFromToken(token);
            jwtTokenManager.addUserToken(user.getId(), jwtId, System.currentTimeMillis());

            // 5. 构建响应
            AuthDto.LoginResponse response = new AuthDto.LoginResponse();
            response.setToken(token);
            response.setTokenExpiresAt(formatTokenExpirationTime(jwtUtil.getTokenExpirationTime()));
            response.setUserInfo(convertToUserInfoResponse(user));

            log.info("微信登录成功 - openid: {}, userId: {}", wechatOpenid, user.getId());
            return response;

        } catch (Exception e) {
            log.error("微信登录失败 - openid: {}, sceneStr: {}", wechatOpenid, sceneStr, e);
            throw new RuntimeException("微信登录失败: " + e.getMessage());
        }
    }

    /**
     * 创建微信用户
     * 当用户通过微信扫码登录但系统中不存在该用户时，自动创建新用户
     * 
     * @param wechatOpenid 微信openid
     * @param sceneStr 场景值（用于获取推广码）
     * @return 新创建的用户
     */
    private User createWechatUser(String wechatOpenid, String sceneStr) {
        try {
            // 1. 生成随机用户名
            String username = generateRandomUsername();

            // 2. 生成基于时间戳的用户ID
            Long userId = generateUserId();

            // 3. 检查是否有推广码信息
            Long inviterId = null;
            if (StringUtils.hasText(sceneStr)) {
                String inviteKey = "wx_login_scene:" + sceneStr + ":invite";
                String inviterIdStr = redisTemplate.opsForValue().get(inviteKey);
                if (StringUtils.hasText(inviterIdStr)) {
                    try {
                        inviterId = Long.valueOf(inviterIdStr);
                        // 验证邀请人是否存在
                        User inviter = userMapper.selectById(inviterId);
                        if (inviter == null) {
                            log.warn("推广码对应的邀请人不存在，忽略邀请关系 - inviterId: {}", inviterId);
                            inviterId = null;
                        } else {
                            log.info("微信用户将绑定推广关系 - newUserId: {}, inviterId: {}, inviterName: {}", 
                                    userId, inviterId, inviter.getUsername());
                            // 使用后删除Redis中的推广码信息
                            redisTemplate.delete(inviteKey);
                        }
                    } catch (NumberFormatException e) {
                        log.warn("推广码信息格式错误，忽略邀请关系 - inviterIdStr: {}", inviterIdStr);
                    }
                }
            }

            // 4. 创建新用户
            User newUser = new User();
            newUser.setId(userId);
            newUser.setWechatOpenid(wechatOpenid); // 设置微信openid
            newUser.setPhone(null); // 微信登录用户暂时没有手机号
            newUser.setUsername(username);
            newUser.setPasswordJwt(null); // 微信登录用户没有密码
            newUser.setRole(1); // 先设置为普通用户，注册成功后再设置为VIP
            newUser.setMembershipExpiresAt(LocalDateTime.now().plusDays(2)); // 设置2天后过期
            newUser.setAvatarUrl(DEFAULT_AVATAR_URL); // 设置默认头像
            newUser.setIsVerified(0); // 未实名认证
            newUser.setInviteCode(generateInviteCode());
            newUser.setInviterId(inviterId); // 设置邀请人ID
            newUser.setPromotionLevel(1); // 新用户默认为1级推广等级
            newUser.setPoints(0);
            newUser.setPointsExpiresAt(null);
            newUser.setCreateTime(LocalDateTime.now());
            newUser.setUpdateTime(LocalDateTime.now());
            newUser.setIsDeleted(0);

            // 5. 保存用户
            int result = userMapper.insert(newUser);
            if (result <= 0) {
                throw new RuntimeException("创建微信用户失败");
            }

            // 6. 如果有邀请关系，更新邀请人的推广等级
            if (inviterId != null) {
                try {
                    promotionLevelCalculator.updateUserPromotionLevelOnRegistration(inviterId);
                    log.info("邀请人推广等级已更新 - inviterId: {}", inviterId);
                } catch (Exception e) {
                    log.error("更新邀请人推广等级失败，但不影响用户创建 - inviterId: {}", inviterId, e);
                }
            }

            // 7. 设置默认VIP身份
            userMembershipService.setDefaultVipForNewUser(userId);

            // 8. 发放新用户注册奖励积分
            try {
                pointsService.grantPoints(userId, 200, "新用户注册奖励");
                log.info("微信新用户注册积分发放成功 - userId: {}, 积分: 200", userId);
                
                // 8.1 如果有邀请人，发放邀请奖励积分
                if (inviterId != null) {
                    pointsService.grantPoints(inviterId, 500, "邀请新用户注册奖励");
                    log.info("邀请人奖励积分发放成功 - inviterId: {}, 积分: 500, newUserId: {}", inviterId, userId);
                }
            } catch (Exception e) {
                log.error("微信用户注册积分发放异常，但不影响注册流程 - userId: {}, inviterId: {}", userId, inviterId, e);
            }

            // 9. 初始化推广等级（微信用户新创建时通常为0粉丝，等级为1）
            try {
                boolean levelUpdated = promotionLevelCalculator.updateUserPromotionLevelOnRegistration(userId);
                if (levelUpdated) {
                    log.info("微信用户推广等级初始化完成 - userId: {}", userId);
                } else {
                    log.warn("微信用户推广等级初始化失败，但不影响创建流程 - userId: {}", userId);
                }
            } catch (Exception e) {
                log.error("微信用户推广等级初始化异常，但不影响创建流程 - userId: {}", userId, e);
            }

            // 10. 重新获取用户信息（包含VIP状态和最新积分）
            User updatedUser = userMapper.selectById(userId);
            
            log.info("微信用户创建成功 - openid: {}, userId: {}, username: {}, inviterId: {}", 
                    wechatOpenid, userId, username, inviterId);
            return updatedUser;

        } catch (Exception e) {
            log.error("创建微信用户失败 - openid: {}, sceneStr: {}", wechatOpenid, sceneStr, e);
            throw new RuntimeException("创建微信用户失败: " + e.getMessage());
        }
    }

    /**
     * 将User实体转换为UserInfoResponse
     */
    private AuthDto.UserInfoResponse convertToUserInfoResponse(User user) {
        AuthDto.UserInfoResponse response = new AuthDto.UserInfoResponse();
        response.setId(String.valueOf(user.getId()));
        response.setPhone(user.getPhone());
        response.setUsername(user.getUsername());
        response.setRealUsername(user.getRealUsername());
        response.setIdNumber(user.getIdNumber());
        
        // 检查会员是否过期，如果过期则调整角色显示
        Integer displayRole = user.getRole();
        boolean isMembershipExpired = false;
        
        if (user.getRole() != null && user.getRole() > 1) {
            // 只有VIP用户才需要检查过期
            if (user.getMembershipExpiresAt() == null || 
                user.getMembershipExpiresAt().isBefore(LocalDateTime.now())) {
                isMembershipExpired = true;
                displayRole = 1; // 过期会员降级为普通用户
                log.info("用户会员已过期，角色显示降级 - userId: {}, originalRole: {}, expiresAt: {}", 
                        user.getId(), user.getRole(), user.getMembershipExpiresAt());
            }
        }
        
        response.setRole(displayRole);
        response.setMembershipExpiresAt(user.getMembershipExpiresAt() != null ? 
            user.getMembershipExpiresAt().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) : null);
        response.setAvatarUrl(user.getAvatarUrl());
        response.setIsVerified(user.getIsVerified());
        response.setInviteCode(user.getInviteCode());
        response.setPromotionLevel(user.getPromotionLevel());
        response.setPoints(user.getPoints());
        response.setPointsExpiresAt(user.getPointsExpiresAt() != null ? 
            user.getPointsExpiresAt().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) : null);
        response.setCreateTime(user.getCreateTime() != null ? 
            user.getCreateTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) : null);
        response.setWechatBound(StringUtils.hasText(user.getWechatOpenid()));
        
        // 添加会员类型信息（基于实际的会员状态）
        String membershipType;
        boolean isExchangeMemberOnly;
        
        if (isMembershipExpired) {
            membershipType = "过期会员";
            isExchangeMemberOnly = false; // 过期会员不参与收益分成
        } else {
            membershipType = membershipUtil.getMembershipTypeDescription(user.getId());
            isExchangeMemberOnly = membershipUtil.isExchangeMemberWithoutRevenue(user.getId());
        }
        
        response.setMembershipType(membershipType);
        response.setIsExchangeMemberOnly(isExchangeMemberOnly);
        
        // 添加会员过期状态信息
        response.setIsMembershipExpired(isMembershipExpired);
        
        // 查询用户最新的积分套餐购买记录
        String latestPointsPackageName = getLatestPointsPackageName(user.getId());
        response.setLatestPointsPackageName(latestPointsPackageName);
        
        return response;
    }

    @Override
    public boolean bindWechatAccount(Long userId, String wechatOpenid) {
        try {
            // 检查用户是否存在
            User user = userMapper.selectById(userId);
            if (user == null) {
                throw new RuntimeException("用户不存在");
            }

            // 检查用户是否已绑定微信
            if (StringUtils.hasText(user.getWechatOpenid())) {
                throw new RuntimeException("用户已绑定其他微信账号");
            }

            // 检查该微信账号是否已被其他用户绑定
            User existingUser = userMapper.selectByWechatOpenid(wechatOpenid);
            if (existingUser != null) {
                throw new RuntimeException("该微信账号已绑定其他用户");
            }

            // 更新用户的微信openid
            user.setWechatOpenid(wechatOpenid);
            user.setUpdateTime(LocalDateTime.now());

            boolean success = userMapper.updateById(user) > 0;
            
            if (success) {
                log.info("微信账号绑定成功 - userId: {}, wechatOpenid: {}", userId, wechatOpenid);
            }

            return success;
        } catch (Exception e) {
            log.error("绑定微信账号失败 - userId: {}, wechatOpenid: {}", userId, wechatOpenid, e);
            throw new RuntimeException("绑定微信账号失败: " + e.getMessage());
        }
    }

    /**
     * 格式化token过期时间
     * @param expirationTime 过期时间
     * @return 格式化后的时间字符串
     */
    private String formatTokenExpirationTime(java.util.Date expirationTime) {
        Instant instant = expirationTime.toInstant();
        LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
        return localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    }
    
    /**
     * 获取用户最新的积分套餐名称
     * @param userId 用户ID
     * @return 积分套餐名称，如果没有购买记录则返回"免费版"
     */
    private String getLatestPointsPackageName(Long userId) {
        try {
            // 查询用户最新的积分订单（已支付状态，status=1表示已支付）
            Order latestPointsOrder = orderMapper.selectLastPointsOrderByUserId(userId, 1);
            
            if (latestPointsOrder == null) {
                return "免费版";
            }
            
            // 根据积分套餐ID查询套餐名称
            PointsPackage pointsPackage = pointsPackageMapper.selectById(latestPointsOrder.getPointsPackageId());
            
            if (pointsPackage == null) {
                log.warn("积分套餐不存在，packageId: {}, userId: {}", latestPointsOrder.getPointsPackageId(), userId);
                return "免费版";
            }
            
            return pointsPackage.getName();
            
        } catch (Exception e) {
            log.error("查询用户最新积分套餐失败，userId: {}", userId, e);
            return "免费版";
        }
    }
} 