using System.Security.Cryptography;
using System.Text;
using HoneyBox.Core.Interfaces;
using HoneyBox.Model.Data;
using HoneyBox.Model.Entities;
using HoneyBox.Model.Models.Auth;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace HoneyBox.Core.Services;

/// <summary>
/// 认证服务实现
/// </summary>
public class AuthService : IAuthService
{
    private readonly HoneyBoxDbContext _dbContext;
    private readonly IUserService _userService;
    private readonly IJwtService _jwtService;
    private readonly IWechatService _wechatService;
    private readonly IIpLocationService _ipLocationService;
    private readonly IRedisService _redisService;
    private readonly JwtSettings _jwtSettings;
    private readonly ILogger<AuthService> _logger;

    // Redis key prefixes
    private const string LoginDebounceKeyPrefix = "login:debounce:";
    private const string SmsCodeKeyPrefix = "sms:code:";
    private const int DebounceSeconds = 3;

    // Refresh Token 配置
    private const int RefreshTokenLength = 64;

    public AuthService(
        HoneyBoxDbContext dbContext,
        IUserService userService,
        IJwtService jwtService,
        IWechatService wechatService,
        IIpLocationService ipLocationService,
        IRedisService redisService,
        JwtSettings jwtSettings,
        ILogger<AuthService> logger)
    {
        _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
        _userService = userService ?? throw new ArgumentNullException(nameof(userService));
        _jwtService = jwtService ?? throw new ArgumentNullException(nameof(jwtService));
        _wechatService = wechatService ?? throw new ArgumentNullException(nameof(wechatService));
        _ipLocationService = ipLocationService ?? throw new ArgumentNullException(nameof(ipLocationService));
        _redisService = redisService ?? throw new ArgumentNullException(nameof(redisService));
        _jwtSettings = jwtSettings ?? throw new ArgumentNullException(nameof(jwtSettings));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }


    /// <summary>
    /// 微信小程序登录
    /// Requirements: 1.1-1.8
    /// </summary>
    public async Task<LoginResult> WechatMiniProgramLoginAsync(string code, int? pid, string? clickId)
    {
        _logger.LogInformation("[AuthService] 微信登录开始，code={Code}, pid={Pid}, clickId={ClickId}", code, pid, clickId);
        
        if (string.IsNullOrWhiteSpace(code))
        {
            _logger.LogWarning("[AuthService] 微信登录失败：code为空");
            return new LoginResult
            {
                Success = false,
                ErrorMessage = "授权code不能为空"
            };
        }

        try
        {
            // 1.6 防抖机制 - 3秒内不允许重复登录
            var debounceKey = $"{LoginDebounceKeyPrefix}wechat:{code}";
            _logger.LogInformation("[AuthService] 检查防抖锁: {Key}", debounceKey);
            var lockAcquired = await _redisService.TryAcquireLockAsync(debounceKey, "1", TimeSpan.FromSeconds(DebounceSeconds));
            if (!lockAcquired)
            {
                _logger.LogWarning("[AuthService] 防抖触发，拒绝重复登录请求: {Code}", code);
                return new LoginResult
                {
                    Success = false,
                    ErrorMessage = "请勿频繁登录"
                };
            }
            _logger.LogInformation("[AuthService] 防抖锁获取成功");

            // 1.1 调用微信API获取openid和unionid
            _logger.LogInformation("[AuthService] 开始调用微信API获取openid...");
            var wechatResult = await _wechatService.GetOpenIdAsync(code);
            _logger.LogInformation("[AuthService] 微信API调用完成，Success={Success}, OpenId={OpenId}, UnionId={UnionId}, Error={Error}", 
                wechatResult.Success, 
                wechatResult.OpenId ?? "null", 
                wechatResult.UnionId ?? "null",
                wechatResult.ErrorMessage ?? "null");
            
            if (!wechatResult.Success)
            {
                _logger.LogWarning("[AuthService] 微信API调用失败: {Error}", wechatResult.ErrorMessage);
                return new LoginResult
                {
                    Success = false,
                    ErrorMessage = wechatResult.ErrorMessage ?? "登录失败，请稍后重试"
                };
            }

            var openId = wechatResult.OpenId!;
            var unionId = wechatResult.UnionId;

            // 1.2 查找用户 - 优先通过unionid查找，其次通过openid查找
            User? user = null;
            if (!string.IsNullOrWhiteSpace(unionId))
            {
                _logger.LogInformation("[AuthService] 尝试通过unionid查找用户: {UnionId}", unionId);
                user = await _userService.GetUserByUnionIdAsync(unionId);
                _logger.LogInformation("[AuthService] unionid查找结果: {Found}", user != null ? $"找到用户ID={user.Id}" : "未找到");
            }
            if (user == null)
            {
                _logger.LogInformation("[AuthService] 尝试通过openid查找用户: {OpenId}", openId);
                user = await _userService.GetUserByOpenIdAsync(openId);
                _logger.LogInformation("[AuthService] openid查找结果: {Found}", user != null ? $"找到用户ID={user.Id}" : "未找到");
            }

            if (user == null)
            {
                // 1.3 用户不存在，创建新用户
                _logger.LogInformation("[AuthService] 用户不存在，开始创建新用户...");
                var createDto = new CreateUserDto
                {
                    OpenId = openId,
                    UnionId = unionId,
                    Nickname = $"用户{Random.Shared.Next(100000, 999999)}",
                    Headimg = GenerateDefaultAvatar(openId),
                    Pid = pid?.ToString(),
                    ClickId = ParseClickId(clickId)
                };

                user = await _userService.CreateUserAsync(createDto);
                _logger.LogInformation("[AuthService] 新用户创建成功: UserId={UserId}, OpenId={OpenId}", user.Id, openId);
            }
            else
            {
                // 1.4 用户存在，更新unionid（如果之前为空）
                if (string.IsNullOrWhiteSpace(user.UnionId) && !string.IsNullOrWhiteSpace(unionId))
                {
                    _logger.LogInformation("[AuthService] 更新用户unionid: UserId={UserId}", user.Id);
                    await _userService.UpdateUserAsync(user.Id, new UpdateUserDto { UnionId = unionId });
                    _logger.LogInformation("[AuthService] unionid更新成功");
                }
            }

            // 1.5 生成双 Token（Access Token + Refresh Token）
            _logger.LogInformation("[AuthService] 开始生成双 Token: UserId={UserId}", user.Id);
            var loginResponse = await GenerateLoginResponseAsync(user, null);
            _logger.LogInformation("[AuthService] 双 Token 生成成功，AccessToken长度={Length}", loginResponse.AccessToken?.Length ?? 0);

            // 3.6 同时在数据库UserAccount表中存储account_token用于兼容旧系统
            _logger.LogInformation("[AuthService] 更新UserAccount表...");
            await CreateOrUpdateAccountTokenAsync(user.Id, loginResponse.AccessToken);
            _logger.LogInformation("[AuthService] UserAccount更新成功");

            _logger.LogInformation("[AuthService] 微信登录成功: UserId={UserId}", user.Id);

            return new LoginResult
            {
                Success = true,
                Token = loginResponse.AccessToken, // 兼容旧版
                UserId = user.Id,
                LoginResponse = loginResponse
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "[AuthService] 微信登录异常: code={Code}, Message={Message}, StackTrace={StackTrace}", 
                code, ex.Message, ex.StackTrace);
            return new LoginResult
            {
                Success = false,
                ErrorMessage = "网络故障，请稍后再试"
            };
        }
    }


    /// <summary>
    /// 手机号验证码登录
    /// Requirements: 2.1-2.7
    /// </summary>
    public async Task<LoginResult> MobileLoginAsync(string mobile, string code, int? pid, string? clickId)
    {
        if (string.IsNullOrWhiteSpace(mobile))
        {
            return new LoginResult
            {
                Success = false,
                ErrorMessage = "手机号不能为空"
            };
        }

        if (string.IsNullOrWhiteSpace(code))
        {
            return new LoginResult
            {
                Success = false,
                ErrorMessage = "验证码不能为空"
            };
        }

        try
        {
            // 2.6 防抖机制 - 3秒内不允许重复登录
            var debounceKey = $"{LoginDebounceKeyPrefix}mobile:{mobile}";
            var lockAcquired = await _redisService.TryAcquireLockAsync(debounceKey, "1", TimeSpan.FromSeconds(DebounceSeconds));
            if (!lockAcquired)
            {
                _logger.LogWarning("Login debounce triggered for mobile: {Mobile}", MaskMobile(mobile));
                return new LoginResult
                {
                    Success = false,
                    ErrorMessage = "请勿频繁登录"
                };
            }

            // 2.1 从Redis获取并验证验证码
            var smsCodeKey = $"{SmsCodeKeyPrefix}{mobile}";
            var storedCode = await _redisService.GetStringAsync(smsCodeKey);

            if (string.IsNullOrWhiteSpace(storedCode) || storedCode != code)
            {
                _logger.LogWarning("SMS code verification failed for mobile: {Mobile}", MaskMobile(mobile));
                return new LoginResult
                {
                    Success = false,
                    ErrorMessage = "验证码错误"
                };
            }

            // 2.2 验证码验证通过后，删除Redis中的验证码
            await _redisService.DeleteAsync(smsCodeKey);

            // 查找用户
            var user = await _userService.GetUserByMobileAsync(mobile);

            if (user == null)
            {
                // 2.3 用户不存在，创建新用户
                var createDto = new CreateUserDto
                {
                    Mobile = mobile,
                    Nickname = $"用户{Random.Shared.Next(100000, 999999)}",
                    Headimg = GenerateDefaultAvatar(mobile),
                    Pid = pid?.ToString(),
                    ClickId = ParseClickId(clickId)
                };

                user = await _userService.CreateUserAsync(createDto);
                _logger.LogInformation("New user created via mobile login: UserId={UserId}, Mobile={Mobile}", user.Id, MaskMobile(mobile));
            }

            // 2.4 生成双 Token（Access Token + Refresh Token）
            var loginResponse = await GenerateLoginResponseAsync(user, null);

            // 3.6 同时在数据库UserAccount表中存储account_token用于兼容旧系统
            await CreateOrUpdateAccountTokenAsync(user.Id, loginResponse.AccessToken);

            _logger.LogInformation("Mobile login successful: UserId={UserId}", user.Id);

            return new LoginResult
            {
                Success = true,
                Token = loginResponse.AccessToken, // 兼容旧版
                UserId = user.Id,
                LoginResponse = loginResponse
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Mobile login failed for mobile: {Mobile}", MaskMobile(mobile));
            return new LoginResult
            {
                Success = false,
                ErrorMessage = "网络故障，请稍后再试"
            };
        }
    }


    /// <summary>
    /// 验证码绑定手机号
    /// Requirements: 5.1-5.5
    /// </summary>
    public async Task<BindMobileResponse> BindMobileAsync(int userId, string mobile, string code)
    {
        if (string.IsNullOrWhiteSpace(mobile))
        {
            throw new ArgumentException("手机号不能为空", nameof(mobile));
        }

        if (string.IsNullOrWhiteSpace(code))
        {
            throw new ArgumentException("验证码不能为空", nameof(code));
        }

        // 5.1 验证短信验证码
        var smsCodeKey = $"{SmsCodeKeyPrefix}{mobile}";
        var storedCode = await _redisService.GetStringAsync(smsCodeKey);

        if (string.IsNullOrWhiteSpace(storedCode) || storedCode != code)
        {
            _logger.LogWarning("SMS code verification failed for bind mobile: UserId={UserId}, Mobile={Mobile}", userId, MaskMobile(mobile));
            throw new InvalidOperationException("验证码错误");
        }

        // 验证码验证通过后删除
        await _redisService.DeleteAsync(smsCodeKey);

        // 获取当前用户
        var currentUser = await _userService.GetUserByIdAsync(userId);
        if (currentUser == null)
        {
            throw new InvalidOperationException("用户不存在");
        }

        // 检查手机号是否已被其他用户绑定
        var existingUser = await _userService.GetUserByMobileAsync(mobile);

        if (existingUser != null && existingUser.Id != userId)
        {
            // 5.2 手机号已被其他用户绑定，需要合并账户
            return await MergeAccountsAsync(currentUser, existingUser);
        }

        // 5.4 手机号未被绑定，直接更新当前用户的手机号
        await _userService.UpdateUserAsync(userId, new UpdateUserDto { Mobile = mobile });
        _logger.LogInformation("Mobile bound successfully: UserId={UserId}, Mobile={Mobile}", userId, MaskMobile(mobile));

        return new BindMobileResponse { Token = null };
    }

    /// <summary>
    /// 微信授权绑定手机号
    /// Requirements: 5.1-5.5
    /// </summary>
    public async Task<BindMobileResponse> WechatBindMobileAsync(int userId, string wechatCode)
    {
        if (string.IsNullOrWhiteSpace(wechatCode))
        {
            throw new ArgumentException("微信授权code不能为空", nameof(wechatCode));
        }

        // 调用微信API获取手机号
        var mobileResult = await _wechatService.GetMobileAsync(wechatCode);
        if (!mobileResult.Success || string.IsNullOrWhiteSpace(mobileResult.Mobile))
        {
            _logger.LogWarning("WeChat get mobile failed: UserId={UserId}, Error={Error}", userId, mobileResult.ErrorMessage);
            throw new InvalidOperationException(mobileResult.ErrorMessage ?? "获取手机号失败");
        }

        var mobile = mobileResult.Mobile;

        // 获取当前用户
        var currentUser = await _userService.GetUserByIdAsync(userId);
        if (currentUser == null)
        {
            throw new InvalidOperationException("用户不存在");
        }

        // 检查手机号是否已被其他用户绑定
        var existingUser = await _userService.GetUserByMobileAsync(mobile);

        if (existingUser != null && existingUser.Id != userId)
        {
            // 5.2 手机号已被其他用户绑定，需要合并账户
            return await MergeAccountsAsync(currentUser, existingUser);
        }

        // 5.4 手机号未被绑定，直接更新当前用户的手机号
        await _userService.UpdateUserAsync(userId, new UpdateUserDto { Mobile = mobile });
        _logger.LogInformation("Mobile bound via WeChat successfully: UserId={UserId}, Mobile={Mobile}", userId, MaskMobile(mobile));

        return new BindMobileResponse { Token = null };
    }

    /// <summary>
    /// 微信手机号快速验证登录
    /// 使用微信getPhoneNumber获取的code直接登录，同时获取openid用于微信支付
    /// </summary>
    public async Task<LoginResult> WechatPhoneLoginAsync(string phoneCode, string? loginCode, int? pid)
    {
        _logger.LogInformation("[AuthService] 微信手机号登录开始，pid={Pid}, hasLoginCode={HasLoginCode}", pid, !string.IsNullOrEmpty(loginCode));

        if (string.IsNullOrWhiteSpace(phoneCode))
        {
            _logger.LogWarning("[AuthService] 微信手机号登录失败：phoneCode为空");
            return new LoginResult
            {
                Success = false,
                ErrorMessage = "手机号授权code不能为空"
            };
        }

        try
        {
            // 防抖机制 - 3秒内不允许重复登录
            var debounceKey = $"{LoginDebounceKeyPrefix}wxphone:{phoneCode}";
            var lockAcquired = await _redisService.TryAcquireLockAsync(debounceKey, "1", TimeSpan.FromSeconds(DebounceSeconds));
            if (!lockAcquired)
            {
                _logger.LogWarning("[AuthService] 防抖触发，拒绝重复登录请求");
                return new LoginResult
                {
                    Success = false,
                    ErrorMessage = "请勿频繁登录"
                };
            }

            // 1. 调用微信API获取手机号
            _logger.LogInformation("[AuthService] 开始调用微信API获取手机号...");
            var mobileResult = await _wechatService.GetMobileAsync(phoneCode);
            
            if (!mobileResult.Success || string.IsNullOrWhiteSpace(mobileResult.Mobile))
            {
                _logger.LogWarning("[AuthService] 获取手机号失败: {Error}", mobileResult.ErrorMessage);
                return new LoginResult
                {
                    Success = false,
                    ErrorMessage = mobileResult.ErrorMessage ?? "获取手机号失败"
                };
            }

            var mobile = mobileResult.Mobile;
            _logger.LogInformation("[AuthService] 获取手机号成功: {Mobile}", MaskMobile(mobile));

            // 2. 如果有loginCode，获取openid
            string? openId = null;
            string? unionId = null;
            if (!string.IsNullOrWhiteSpace(loginCode))
            {
                _logger.LogInformation("[AuthService] 开始调用微信API获取openid...");
                var wechatResult = await _wechatService.GetOpenIdAsync(loginCode);
                if (wechatResult.Success)
                {
                    openId = wechatResult.OpenId;
                    unionId = wechatResult.UnionId;
                    _logger.LogInformation("[AuthService] 获取openid成功: {OpenId}", openId);
                }
                else
                {
                    _logger.LogWarning("[AuthService] 获取openid失败: {Error}，继续登录但无法使用微信支付", wechatResult.ErrorMessage);
                }
            }

            // 3. 根据手机号查找用户
            var user = await _userService.GetUserByMobileAsync(mobile);

            if (user == null)
            {
                // 用户不存在，创建新用户
                _logger.LogInformation("[AuthService] 用户不存在，开始创建新用户...");
                var createDto = new CreateUserDto
                {
                    Mobile = mobile,
                    OpenId = openId,
                    UnionId = unionId,
                    Nickname = $"用户{Random.Shared.Next(100000, 999999)}",
                    Headimg = GenerateDefaultAvatar(mobile),
                    Pid = pid?.ToString()
                };

                user = await _userService.CreateUserAsync(createDto);
                _logger.LogInformation("[AuthService] 新用户创建成功: UserId={UserId}, Mobile={Mobile}, OpenId={OpenId}", 
                    user.Id, MaskMobile(mobile), openId ?? "null");
            }
            else
            {
                _logger.LogInformation("[AuthService] 找到已有用户: UserId={UserId}", user.Id);
                
                // 4. 如果用户存在但没有openid，更新openid
                if (!string.IsNullOrWhiteSpace(openId) && string.IsNullOrWhiteSpace(user.OpenId))
                {
                    _logger.LogInformation("[AuthService] 更新用户openid: UserId={UserId}", user.Id);
                    await _userService.UpdateUserAsync(user.Id, new UpdateUserDto { OpenId = openId, UnionId = unionId });
                }
            }

            // 5. 生成双 Token
            _logger.LogInformation("[AuthService] 开始生成双 Token: UserId={UserId}", user.Id);
            var loginResponse = await GenerateLoginResponseAsync(user, null);

            // 更新UserAccount表
            await CreateOrUpdateAccountTokenAsync(user.Id, loginResponse.AccessToken);

            _logger.LogInformation("[AuthService] 微信手机号登录成功: UserId={UserId}, HasOpenId={HasOpenId}", user.Id, !string.IsNullOrWhiteSpace(openId));

            return new LoginResult
            {
                Success = true,
                Token = loginResponse.AccessToken,
                UserId = user.Id,
                LoginResponse = loginResponse
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "[AuthService] 微信手机号登录异常: {Message}", ex.Message);
            return new LoginResult
            {
                Success = false,
                ErrorMessage = "网络故障，请稍后再试"
            };
        }
    }


    /// <summary>
    /// 记录登录信息
    /// Requirements: 6.1, 6.3, 6.4
    /// </summary>
    public async Task<RecordLoginResponse> RecordLoginAsync(int userId, string? device, string? deviceInfo)
    {
        var user = await _userService.GetUserByIdAsync(userId);
        if (user == null)
        {
            throw new InvalidOperationException("用户不存在");
        }

        try
        {
            // 获取客户端IP（这里使用空字符串作为占位符，实际IP应从Controller传入）
            var clientIp = deviceInfo ?? string.Empty;

            // 6.2 解析IP地址获取地理位置
            IpLocationResult? locationResult = null;
            if (!string.IsNullOrWhiteSpace(clientIp))
            {
                locationResult = await _ipLocationService.GetLocationAsync(clientIp);
            }

            var now = DateTime.UtcNow;
            var today = DateOnly.FromDateTime(now);

            // 6.1 记录登录日志
            var loginLog = new UserLoginLog
            {
                UserId = userId,
                LoginDate = today,
                LoginTime = now,
                LastLoginTime = now,
                Device = device,
                Ip = clientIp,
                Location = locationResult?.Success == true 
                    ? $"{locationResult.Province}{locationResult.City}" 
                    : null,
                Year = now.Year,
                Month = now.Month,
                Week = GetWeekOfYear(now)
            };

            await _dbContext.UserLoginLogs.AddAsync(loginLog);

            // 6.3 更新UserAccount表中的最后登录时间和IP信息
            var userAccount = await _dbContext.UserAccounts.FirstOrDefaultAsync(ua => ua.UserId == userId);
            if (userAccount != null)
            {
                userAccount.LastLoginTime = now;
                userAccount.LastLoginIp = clientIp;
                if (locationResult?.Success == true)
                {
                    userAccount.IpProvince = locationResult.Province;
                    userAccount.IpCity = locationResult.City;
                    userAccount.IpAdcode = locationResult.Adcode;
                }
                _dbContext.UserAccounts.Update(userAccount);
            }

            // 更新用户最后登录时间
            user.LastLoginTime = now;
            _dbContext.Users.Update(user);

            await _dbContext.SaveChangesAsync();

            _logger.LogInformation("Login recorded: UserId={UserId}, Device={Device}, IP={IP}", userId, device, clientIp);

            // 6.4 返回用户的uid、昵称和头像
            return new RecordLoginResponse
            {
                Uid = user.Uid,
                Nickname = user.Nickname,
                Headimg = user.HeadImg
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to record login: UserId={UserId}", userId);
            throw;
        }
    }

    /// <summary>
    /// H5绑定手机号（无需验证码）
    /// Requirements: 13.1
    /// </summary>
    public async Task<BindMobileResponse> BindMobileH5Async(int userId, string mobile)
    {
        if (string.IsNullOrWhiteSpace(mobile))
        {
            throw new ArgumentException("手机号不能为空", nameof(mobile));
        }

        // 获取当前用户
        var currentUser = await _userService.GetUserByIdAsync(userId);
        if (currentUser == null)
        {
            throw new InvalidOperationException("用户不存在");
        }

        // 检查手机号是否已被其他用户绑定
        var existingUser = await _userService.GetUserByMobileAsync(mobile);

        if (existingUser != null && existingUser.Id != userId)
        {
            // 手机号已被其他用户绑定，需要合并账户
            return await MergeAccountsAsync(currentUser, existingUser);
        }

        // 手机号未被绑定，直接更新当前用户的手机号
        await _userService.UpdateUserAsync(userId, new UpdateUserDto { Mobile = mobile });
        _logger.LogInformation("H5 Mobile bound successfully: UserId={UserId}, Mobile={Mobile}", userId, MaskMobile(mobile));

        return new BindMobileResponse { Token = null };
    }

    /// <summary>
    /// 账号注销
    /// Requirements: 7.1-7.3
    /// </summary>
    public async Task LogOffAsync(int userId, int type)
    {
        var user = await _userService.GetUserByIdAsync(userId);
        if (user == null)
        {
            throw new InvalidOperationException("用户不存在");
        }

        try
        {
            // 7.1 记录注销请求日志
            var action = type == 0 ? "注销账号" : "取消注销";
            _logger.LogInformation("User log off request: UserId={UserId}, Type={Type}, Action={Action}", userId, type, action);

            // 这里可以添加更多的注销逻辑，比如：
            // - 将用户状态设置为已注销
            // - 清理用户相关的缓存
            // - 发送通知等

            if (type == 0)
            {
                // 注销账号 - 可以设置用户状态为禁用
                user.Status = 0;
                _dbContext.Users.Update(user);
                await _dbContext.SaveChangesAsync();
                _logger.LogInformation("User account deactivated: UserId={UserId}", userId);
            }
            else if (type == 1)
            {
                // 取消注销 - 恢复用户状态
                user.Status = 1;
                _dbContext.Users.Update(user);
                await _dbContext.SaveChangesAsync();
                _logger.LogInformation("User account reactivated: UserId={UserId}", userId);
            }

            // 7.2 返回注销成功的消息（通过不抛出异常来表示成功）
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to process log off: UserId={UserId}, Type={Type}", userId, type);
            throw;
        }
    }


    #region Refresh Token Methods

    /// <summary>
    /// 生成 Refresh Token 并存储到数据库
    /// Requirements: 1.4, 1.5, 4.1
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <param name="ipAddress">客户端 IP 地址</param>
    /// <returns>生成的 Refresh Token 明文</returns>
    private async Task<string> GenerateRefreshTokenAsync(int userId, string? ipAddress)
    {
        // 生成随机 Refresh Token
        var refreshToken = GenerateSecureRandomString(RefreshTokenLength);
        
        // 计算 SHA256 哈希值用于存储
        var tokenHash = ComputeSha256Hash(refreshToken);
        
        // 计算过期时间（7天）
        var expiresAt = DateTime.Now.AddDays(_jwtSettings.RefreshTokenExpirationDays);
        
        // 创建数据库记录
        var userRefreshToken = new UserRefreshToken
        {
            UserId = userId,
            TokenHash = tokenHash,
            ExpiresAt = expiresAt,
            CreatedAt = DateTime.Now,
            CreatedByIp = ipAddress
        };
        
        await _dbContext.UserRefreshTokens.AddAsync(userRefreshToken);
        await _dbContext.SaveChangesAsync();
        
        _logger.LogInformation("Generated refresh token for user {UserId}, expires at {ExpiresAt}", userId, expiresAt);
        
        return refreshToken;
    }

    /// <summary>
    /// 生成登录响应（包含双 Token）
    /// Requirements: 1.1, 1.2, 1.3, 1.4, 1.5
    /// </summary>
    /// <param name="user">用户实体</param>
    /// <param name="ipAddress">客户端 IP 地址</param>
    /// <returns>登录响应</returns>
    private async Task<LoginResponse> GenerateLoginResponseAsync(User user, string? ipAddress)
    {
        // 生成 Access Token (JWT)
        var accessToken = _jwtService.GenerateToken(user);
        
        // 生成 Refresh Token 并存储
        var refreshToken = await GenerateRefreshTokenAsync(user.Id, ipAddress);
        
        // 计算 Access Token 过期时间（秒）
        var expiresIn = _jwtSettings.ExpirationMinutes * 60;
        
        return new LoginResponse
        {
            AccessToken = accessToken,
            RefreshToken = refreshToken,
            ExpiresIn = expiresIn,
            UserId = user.Id
        };
    }

    /// <summary>
    /// 刷新 Token
    /// Requirements: 2.1-2.6
    /// </summary>
    public async Task<RefreshTokenResult> RefreshTokenAsync(string refreshToken, string? ipAddress)
    {
        if (string.IsNullOrWhiteSpace(refreshToken))
        {
            _logger.LogWarning("Refresh token is empty");
            return RefreshTokenResult.Fail("刷新令牌不能为空");
        }

        try
        {
            // 计算 Token 哈希值
            var tokenHash = ComputeSha256Hash(refreshToken);
            
            // 查找 Token 记录
            var storedToken = await _dbContext.UserRefreshTokens
                .Include(t => t.User)
                .FirstOrDefaultAsync(t => t.TokenHash == tokenHash);
            
            if (storedToken == null)
            {
                _logger.LogWarning("Refresh token not found: {TokenHash}", tokenHash.Substring(0, 8) + "...");
                return RefreshTokenResult.Fail("无效的刷新令牌");
            }
            
            // 检查是否已过期
            if (storedToken.IsExpired)
            {
                _logger.LogWarning("Refresh token expired for user {UserId}", storedToken.UserId);
                return RefreshTokenResult.Fail("刷新令牌已过期");
            }
            
            // 检查是否已撤销
            if (storedToken.IsRevoked)
            {
                _logger.LogWarning("Refresh token revoked for user {UserId}", storedToken.UserId);
                return RefreshTokenResult.Fail("刷新令牌已失效");
            }
            
            // 检查用户是否存在且有效
            var user = storedToken.User;
            if (user == null)
            {
                _logger.LogWarning("User not found for refresh token");
                return RefreshTokenResult.Fail("用户不存在");
            }
            
            if (user.Status == 0)
            {
                _logger.LogWarning("User {UserId} is disabled", user.Id);
                return RefreshTokenResult.Fail("账号已被禁用");
            }
            
            // Token 轮换：生成新的 Refresh Token
            var newRefreshToken = GenerateSecureRandomString(RefreshTokenLength);
            var newTokenHash = ComputeSha256Hash(newRefreshToken);
            
            // 撤销旧 Token 并记录关联关系
            storedToken.RevokedAt = DateTime.Now;
            storedToken.RevokedByIp = ipAddress;
            storedToken.ReplacedByToken = newTokenHash;
            
            // 创建新的 Token 记录
            var newUserRefreshToken = new UserRefreshToken
            {
                UserId = user.Id,
                TokenHash = newTokenHash,
                ExpiresAt = DateTime.Now.AddDays(_jwtSettings.RefreshTokenExpirationDays),
                CreatedAt = DateTime.Now,
                CreatedByIp = ipAddress
            };
            
            await _dbContext.UserRefreshTokens.AddAsync(newUserRefreshToken);
            await _dbContext.SaveChangesAsync();
            
            // 生成新的 Access Token
            var accessToken = _jwtService.GenerateToken(user);
            var expiresIn = _jwtSettings.ExpirationMinutes * 60;
            
            // 更新 UserAccount 表中的 token（兼容旧系统）
            await CreateOrUpdateAccountTokenAsync(user.Id, accessToken);
            
            _logger.LogInformation("Token refreshed successfully for user {UserId}", user.Id);
            
            return RefreshTokenResult.Ok(new LoginResponse
            {
                AccessToken = accessToken,
                RefreshToken = newRefreshToken,
                ExpiresIn = expiresIn,
                UserId = user.Id
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error refreshing token");
            return RefreshTokenResult.Fail("刷新令牌失败，请稍后重试");
        }
    }

    /// <summary>
    /// 撤销 Token
    /// Requirements: 4.4
    /// </summary>
    public async Task RevokeTokenAsync(string refreshToken, string? ipAddress)
    {
        if (string.IsNullOrWhiteSpace(refreshToken))
        {
            _logger.LogWarning("Cannot revoke empty refresh token");
            return;
        }

        try
        {
            // 计算 Token 哈希值
            var tokenHash = ComputeSha256Hash(refreshToken);
            
            // 查找 Token 记录
            var storedToken = await _dbContext.UserRefreshTokens
                .FirstOrDefaultAsync(t => t.TokenHash == tokenHash);
            
            if (storedToken == null)
            {
                _logger.LogWarning("Refresh token not found for revocation");
                return;
            }
            
            // 如果已经撤销，直接返回
            if (storedToken.IsRevoked)
            {
                _logger.LogInformation("Refresh token already revoked");
                return;
            }
            
            // 撤销 Token
            storedToken.RevokedAt = DateTime.Now;
            storedToken.RevokedByIp = ipAddress;
            
            await _dbContext.SaveChangesAsync();
            
            _logger.LogInformation("Refresh token revoked for user {UserId}", storedToken.UserId);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error revoking refresh token");
            throw;
        }
    }

    /// <summary>
    /// 撤销用户的所有 Token
    /// Requirements: 4.4
    /// </summary>
    public async Task RevokeAllUserTokensAsync(int userId, string? ipAddress)
    {
        try
        {
            // 查找用户所有有效的 Token
            var activeTokens = await _dbContext.UserRefreshTokens
                .Where(t => t.UserId == userId && t.RevokedAt == null)
                .ToListAsync();
            
            if (!activeTokens.Any())
            {
                _logger.LogInformation("No active tokens found for user {UserId}", userId);
                return;
            }
            
            var now = DateTime.Now;
            foreach (var token in activeTokens)
            {
                token.RevokedAt = now;
                token.RevokedByIp = ipAddress;
            }
            
            await _dbContext.SaveChangesAsync();
            
            _logger.LogInformation("Revoked {Count} tokens for user {UserId}", activeTokens.Count, userId);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error revoking all tokens for user {UserId}", userId);
            throw;
        }
    }

    #endregion

    #region Private Helper Methods

    /// <summary>
    /// 合并账户 - 将当前用户的openid迁移到手机号用户
    /// </summary>
    private async Task<BindMobileResponse> MergeAccountsAsync(User currentUser, User mobileUser)
    {
        using var transaction = await _dbContext.Database.BeginTransactionAsync();
        try
        {
            _logger.LogInformation("Merging accounts: CurrentUserId={CurrentUserId}, MobileUserId={MobileUserId}", 
                currentUser.Id, mobileUser.Id);

            // 5.2 将当前用户的openid迁移到手机号用户
            if (!string.IsNullOrWhiteSpace(currentUser.OpenId))
            {
                mobileUser.OpenId = currentUser.OpenId;
            }
            if (!string.IsNullOrWhiteSpace(currentUser.UnionId))
            {
                mobileUser.UnionId = currentUser.UnionId;
            }
            mobileUser.UpdatedAt = DateTime.UtcNow;
            _dbContext.Users.Update(mobileUser);

            // 删除当前用户的账户记录
            var currentUserAccount = await _dbContext.UserAccounts.FirstOrDefaultAsync(ua => ua.UserId == currentUser.Id);
            if (currentUserAccount != null)
            {
                _dbContext.UserAccounts.Remove(currentUserAccount);
            }

            // 删除当前用户
            _dbContext.Users.Remove(currentUser);

            await _dbContext.SaveChangesAsync();
            await transaction.CommitAsync();

            // 5.3 生成新的token
            var newToken = _jwtService.GenerateToken(mobileUser);
            await CreateOrUpdateAccountTokenAsync(mobileUser.Id, newToken);

            _logger.LogInformation("Accounts merged successfully: NewUserId={NewUserId}", mobileUser.Id);

            return new BindMobileResponse { Token = newToken };
        }
        catch (Exception ex)
        {
            await transaction.RollbackAsync();
            _logger.LogError(ex, "Failed to merge accounts: CurrentUserId={CurrentUserId}, MobileUserId={MobileUserId}", 
                currentUser.Id, mobileUser.Id);
            throw;
        }
    }

    /// <summary>
    /// 创建或更新账户Token（用于兼容旧系统）
    /// </summary>
    private async Task CreateOrUpdateAccountTokenAsync(int userId, string jwtToken)
    {
        var tokenNum = GenerateRandomString(10);
        var time = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
        var accountToken = ComputeMd5($"{userId}{tokenNum}{time}");

        var userAccount = await _dbContext.UserAccounts.FirstOrDefaultAsync(ua => ua.UserId == userId);
        
        if (userAccount == null)
        {
            userAccount = new UserAccount
            {
                UserId = userId,
                AccountToken = accountToken,
                TokenNum = tokenNum,
                TokenTime = DateTime.UtcNow,
                LastLoginTime = DateTime.UtcNow,
                LastLoginIp = string.Empty
            };
            await _dbContext.UserAccounts.AddAsync(userAccount);
        }
        else
        {
            userAccount.AccountToken = accountToken;
            userAccount.TokenNum = tokenNum;
            userAccount.TokenTime = DateTime.UtcNow;
            userAccount.LastLoginTime = DateTime.UtcNow;
            _dbContext.UserAccounts.Update(userAccount);
        }

        await _dbContext.SaveChangesAsync();
    }

    /// <summary>
    /// 生成默认头像URL
    /// </summary>
    private static string GenerateDefaultAvatar(string seed)
    {
        // 使用种子生成一个简单的默认头像URL
        // 实际项目中可以使用Identicon库或其他头像生成服务
        var hash = ComputeMd5(seed);
        return $"https://api.dicebear.com/7.x/identicon/svg?seed={hash}";
    }

    /// <summary>
    /// 计算MD5哈希
    /// </summary>
    private static string ComputeMd5(string input)
    {
        var inputBytes = Encoding.UTF8.GetBytes(input);
        var hashBytes = MD5.HashData(inputBytes);
        return Convert.ToHexString(hashBytes).ToLowerInvariant();
    }

    /// <summary>
    /// 生成随机字符串
    /// </summary>
    private static string GenerateRandomString(int length)
    {
        const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        var result = new char[length];
        for (int i = 0; i < length; i++)
        {
            result[i] = chars[Random.Shared.Next(chars.Length)];
        }
        return new string(result);
    }

    /// <summary>
    /// 解析ClickId
    /// </summary>
    private static int? ParseClickId(string? clickId)
    {
        if (string.IsNullOrWhiteSpace(clickId))
            return null;
        
        return int.TryParse(clickId, out var result) ? result : null;
    }

    /// <summary>
    /// 脱敏手机号
    /// </summary>
    private static string MaskMobile(string mobile)
    {
        if (string.IsNullOrWhiteSpace(mobile) || mobile.Length < 7)
            return "***";
        
        return $"{mobile.Substring(0, 3)}****{mobile.Substring(mobile.Length - 4)}";
    }

    /// <summary>
    /// 获取年份中的周数
    /// </summary>
    private static int GetWeekOfYear(DateTime date)
    {
        var cal = System.Globalization.CultureInfo.CurrentCulture.Calendar;
        return cal.GetWeekOfYear(date, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Monday);
    }

    /// <summary>
    /// 计算 SHA256 哈希值
    /// Requirements: 4.1
    /// </summary>
    private static string ComputeSha256Hash(string input)
    {
        var inputBytes = Encoding.UTF8.GetBytes(input);
        var hashBytes = SHA256.HashData(inputBytes);
        return Convert.ToHexString(hashBytes).ToLowerInvariant();
    }

    /// <summary>
    /// 生成安全的随机字符串（用于 Refresh Token）
    /// </summary>
    private static string GenerateSecureRandomString(int length)
    {
        var randomBytes = new byte[length];
        using var rng = RandomNumberGenerator.Create();
        rng.GetBytes(randomBytes);
        return Convert.ToBase64String(randomBytes)
            .Replace("+", "-")
            .Replace("/", "_")
            .Replace("=", "")
            .Substring(0, length);
    }

    #endregion
}
