using System.Text.Json;
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 UserService : BaseService<User, int>, IUserService
{
    private readonly ILogger<UserService> _logger;
    private readonly IConfigService _configService;

    public UserService(HoneyBoxDbContext dbContext, ILogger<UserService> logger, IConfigService configService)
        : base(dbContext)
    {
        _logger = logger;
        _configService = configService;
    }

    /// <inheritdoc/>
    public async Task<User?> GetUserByIdAsync(int userId)
    {
        return await _dbSet.FirstOrDefaultAsync(u => u.Id == userId);
    }

    /// <inheritdoc/>
    public async Task<User?> GetUserByOpenIdAsync(string openId)
    {
        if (string.IsNullOrWhiteSpace(openId))
            return null;

        return await _dbSet.FirstOrDefaultAsync(u => u.OpenId == openId);
    }

    /// <inheritdoc/>
    public async Task<User?> GetUserByUnionIdAsync(string unionId)
    {
        if (string.IsNullOrWhiteSpace(unionId))
            return null;

        return await _dbSet.FirstOrDefaultAsync(u => u.UnionId == unionId);
    }

    /// <inheritdoc/>
    public async Task<User?> GetUserByMobileAsync(string mobile)
    {
        if (string.IsNullOrWhiteSpace(mobile))
            return null;

        return await _dbSet.FirstOrDefaultAsync(u => u.Mobile == mobile);
    }

    /// <inheritdoc/>
    public async Task<User> CreateUserAsync(CreateUserDto dto)
    {
        if (dto == null)
            throw new ArgumentNullException(nameof(dto));

        // Generate UID based on config
        var uid = await GenerateUidAsync();

        // 处理推荐人ID - 支持通过 ID 或 uid 查找
        var pid = 0;
        if (!string.IsNullOrWhiteSpace(dto.Pid))
        {
            // 先尝试作为用户ID查找（如果是数字）
            if (int.TryParse(dto.Pid, out var pidInt) && pidInt > 0)
            {
                var inviterById = await _dbSet.FirstOrDefaultAsync(u => u.Id == pidInt);
                if (inviterById != null)
                {
                    pid = inviterById.Id;
                    _logger.LogInformation("通过用户ID找到推荐人: Pid={Pid}", pid);
                }
            }
            
            // 如果还没找到，尝试作为 uid 查找
            if (pid == 0)
            {
                var inviterByUid = await _dbSet.FirstOrDefaultAsync(u => u.Uid == dto.Pid);
                if (inviterByUid != null)
                {
                    pid = inviterByUid.Id;
                    _logger.LogInformation("通过UID找到推荐人: Uid={Uid}, Pid={Pid}", dto.Pid, pid);
                }
                else
                {
                    _logger.LogWarning("未找到推荐人: Pid={Pid}", dto.Pid);
                }
            }
        }

        var user = new User
        {
            OpenId = dto.OpenId ?? string.Empty,
            UnionId = dto.UnionId,
            Mobile = dto.Mobile,
            Uid = uid,
            Nickname = dto.Nickname ?? $"User{Random.Shared.Next(1000, 9999)}",
            HeadImg = dto.Headimg ?? string.Empty,
            Pid = pid,
            ClickId = dto.ClickId,
            Money = 0,
            Money2 = 0,
            Integral = 0,
            Score = 0,
            Vip = 0,
            Status = 1,
            IsTest = 0,
            CreatedAt = DateTime.UtcNow,
            UpdatedAt = DateTime.UtcNow
        };

        await _dbSet.AddAsync(user);
        await _dbContext.SaveChangesAsync();

        _logger.LogInformation("User created: Id={UserId}, Uid={Uid}, OpenId={OpenId}, Pid={Pid}", 
            user.Id, user.Uid, user.OpenId, user.Pid);

        return user;
    }

    /// <inheritdoc/>
    public async Task UpdateUserAsync(int userId, UpdateUserDto dto)
    {
        if (dto == null)
            throw new ArgumentNullException(nameof(dto));

        var user = await GetUserByIdAsync(userId);
        if (user == null)
            throw new InvalidOperationException($"User with id {userId} not found");

        if (!string.IsNullOrWhiteSpace(dto.Nickname))
            user.Nickname = dto.Nickname;

        if (!string.IsNullOrWhiteSpace(dto.Headimg))
            user.HeadImg = dto.Headimg;

        if (!string.IsNullOrWhiteSpace(dto.Mobile))
            user.Mobile = dto.Mobile;

        if (!string.IsNullOrWhiteSpace(dto.OpenId))
            user.OpenId = dto.OpenId;

        if (!string.IsNullOrWhiteSpace(dto.UnionId))
            user.UnionId = dto.UnionId;

        user.UpdatedAt = DateTime.UtcNow;

        _dbSet.Update(user);
        await _dbContext.SaveChangesAsync();

        _logger.LogInformation($"User updated: Id={user.Id}");
    }

    /// <inheritdoc/>
    public async Task<UserInfoDto?> GetUserInfoAsync(int userId)
    {
        var user = await GetUserByIdAsync(userId);
        if (user == null)
            return null;

        var couponCount = await _dbContext.CouponReceives
            .Where(cr => cr.UserId == userId && cr.State == 0)
            .CountAsync();

        var registrationDays = (int)(DateTime.UtcNow - user.CreatedAt).TotalDays;

        var maskedMobile = MaskMobileNumber(user.Mobile);
        var mobileIs = string.IsNullOrWhiteSpace(user.Mobile) ? 0 : 1;

        // 计算权益等级信息
        var quanYiLevel = await CalculateQuanYiLevelAsync(user.OuQi ?? 0, user.OuQiLevel ?? 0);

        return new UserInfoDto
        {
            Id = user.Id,
            Uid = user.Uid,
            Nickname = user.Nickname,
            Headimg = user.HeadImg,
            Mobile = maskedMobile,
            MobileIs = mobileIs,
            Money = user.Money,
            Money2 = user.Money2 ?? 0,
            Integral = user.Integral,
            Score = user.Score,
            Vip = user.Vip,
            VipImgurl = GetEquityImageUrl(user.Vip),
            Coupon = couponCount,
            Day = registrationDays,
            QuanYiLevel = quanYiLevel
        };
    }

    /// <summary>
    /// 计算用户权益等级信息
    /// </summary>
    /// <param name="ouQi">用户欧气值</param>
    /// <param name="ouQiLevel">用户欧气等级</param>
    /// <returns>权益等级DTO</returns>
    private async Task<QuanYiLevelDto> CalculateQuanYiLevelAsync(int ouQi, int ouQiLevel)
    {
        // 从数据库读取等级配置
        var equityLevels = await _dbContext.EquityLevels
            .Where(e => e.DeletedAt == null)
            .OrderBy(e => e.Level)
            .ToListAsync();

        var levelThresholds = equityLevels.Any()
            ? equityLevels.ToDictionary(e => e.Level, e => e.Number)
            : new Dictionary<int, int>
            {
                { 0, 0 },
                { 1, 100 },
                { 2, 500 },
                { 3, 1000 },
                { 4, 3000 },
                { 5, 6000 },
                { 6, 10000 },
                { 7, 20000 }
            };

        var maxLevel = levelThresholds.Keys.DefaultIfEmpty(0).Max();
        var nextLevel = ouQiLevel + 1;
        var currentLevelOuQi = levelThresholds.GetValueOrDefault(ouQiLevel, 0);
        var nextOuQi = levelThresholds.GetValueOrDefault(nextLevel, 0);

        // 计算差值和进度
        int cha;
        int jindu;
        if (nextLevel > maxLevel || nextOuQi == 0)
        {
            // 已满级
            cha = -1;
            jindu = 100;
        }
        else
        {
            cha = Math.Max(0, nextOuQi - ouQi);
            // 计算当前等级内的进度
            var levelRange = nextOuQi - currentLevelOuQi;
            var progress = ouQi - currentLevelOuQi;
            jindu = levelRange > 0 ? Math.Min(100, Math.Max(0, progress * 100 / levelRange)) : 0;
        }

        return new QuanYiLevelDto
        {
            Level = ouQiLevel,
            Cha = cha,
            Jindu = jindu
        };
    }

    /// <inheritdoc/>
    public async Task<int> CalculateVipLevelAsync(int userId, int currentVip)
    {
        var user = await GetUserByIdAsync(userId);
        if (user == null)
            return currentVip;

        // Get all equity levels ordered by level
        var equityLevels = await _dbContext.EquityLevels
            .Where(v => v.DeletedAt == null)
            .OrderBy(v => v.Level)
            .ToListAsync();

        if (!equityLevels.Any())
            return currentVip;

        // Calculate VIP level based on total spending (Money)
        var totalSpending = user.Money;

        int newVipLevel = 0;
        foreach (var equityLevel in equityLevels)
        {
            if (totalSpending >= equityLevel.Number)
            {
                newVipLevel = equityLevel.Level;
            }
            else
            {
                break;
            }
        }

        return newVipLevel;
    }

    /// <summary>
    /// Generate a unique UID for new user
    /// </summary>
    private async Task<string> GenerateUidAsync()
    {
        // 读取用户配置
        var userConfigJson = await _configService.GetConfigValueAsync("user_config");
        
        int uidType = 2;  // 默认数字ID
        int uidLength = 6; // 默认6位
        
        if (!string.IsNullOrEmpty(userConfigJson))
        {
            try
            {
                var userConfig = JsonSerializer.Deserialize<Dictionary<string, string>>(userConfigJson,
                    new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
                
                if (userConfig != null)
                {
                    if (userConfig.TryGetValue("uid_type", out var uidTypeStr) && int.TryParse(uidTypeStr, out var parsedType))
                    {
                        uidType = parsedType;
                    }
                    if (userConfig.TryGetValue("uid_length", out var uidLengthStr) && int.TryParse(uidLengthStr, out var parsedLength))
                    {
                        uidLength = parsedLength;
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Failed to parse user_config, using defaults");
            }
        }

        // 根据配置生成UID
        string uid;
        int maxAttempts = 100;
        int attempt = 0;
        
        do
        {
            uid = uidType switch
            {
                1 => await GenerateRealIdUidAsync(),           // 真实ID（基于数据库自增）
                2 => GenerateNumericUid(uidLength),            // 数字ID
                3 => GenerateAlphanumericUid(uidLength),       // 随机字符和数字
                _ => GenerateNumericUid(uidLength)
            };
            attempt++;
        }
        while (await UidExistsAsync(uid) && attempt < maxAttempts);

        if (attempt >= maxAttempts)
        {
            // 如果多次尝试都重复，使用时间戳+随机数作为后备方案
            uid = $"{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}{Random.Shared.Next(100, 999)}";
        }

        return uid;
    }

    /// <summary>
    /// 检查UID是否已存在
    /// </summary>
    private async Task<bool> UidExistsAsync(string uid)
    {
        return await _dbSet.AnyAsync(u => u.Uid == uid);
    }

    /// <summary>
    /// 生成真实ID类型的UID（基于当前最大用户ID）
    /// </summary>
    private async Task<string> GenerateRealIdUidAsync()
    {
        var maxId = await _dbSet.MaxAsync(u => (int?)u.Id) ?? 0;
        return (maxId + 1).ToString();
    }

    /// <summary>
    /// 生成纯数字UID
    /// </summary>
    private static string GenerateNumericUid(int length)
    {
        if (length < 4) length = 4;
        if (length > 12) length = 12;
        
        // 第一位不能是0
        var firstDigit = Random.Shared.Next(1, 10).ToString();
        var remainingLength = length - 1;
        
        var remaining = new char[remainingLength];
        for (int i = 0; i < remainingLength; i++)
        {
            remaining[i] = (char)('0' + Random.Shared.Next(0, 10));
        }
        
        return firstDigit + new string(remaining);
    }

    /// <summary>
    /// 生成字母数字混合UID
    /// </summary>
    private static string GenerateAlphanumericUid(int length)
    {
        if (length < 4) length = 4;
        if (length > 16) length = 16;
        
        const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        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>
    /// Mask mobile number for privacy (e.g., 13812345678 -> 138****5678)
    /// </summary>
    private string? MaskMobileNumber(string? mobile)
    {
        if (string.IsNullOrWhiteSpace(mobile) || mobile.Length < 11)
            return null;

        return $"{mobile.Substring(0, 3)}****{mobile.Substring(mobile.Length - 4)}";
    }

    /// <summary>
    /// Get equity image URL based on equity level
    /// </summary>
    private string? GetEquityImageUrl(int equityLevel)
    {
        if (equityLevel <= 0)
            return null;

        // Return a placeholder URL - actual URLs should be configured
        return $"https://example.com/equity/level_{equityLevel}.png";
    }
}
