namespace DramaLing.Api.Services.Domain.Learning;

/// <summary>
/// CEFR 等級服務介面
/// </summary>
public interface ICEFRLevelService
{
    /// <summary>
    /// 取得 CEFR 等級的數字索引
    /// </summary>
    int GetLevelIndex(string level);

    /// <summary>
    /// 判定詞彙對特定用戶是否為高價值
    /// </summary>
    bool IsHighValueForUser(string wordLevel, string userLevel);

    /// <summary>
    /// 取得用戶的目標學習等級範圍
    /// </summary>
    string GetTargetLevelRange(string userLevel);

    /// <summary>
    /// 取得下一個等級
    /// </summary>
    string GetNextLevel(string currentLevel);

    /// <summary>
    /// 計算等級進度百分比
    /// </summary>
    double CalculateLevelProgress(string currentLevel, int masteredWords, int totalWords);

    /// <summary>
    /// 根據掌握詞彙數推薦等級
    /// </summary>
    string RecommendLevel(Dictionary<string, int> masteredWordsByLevel);

    /// <summary>
    /// 驗證等級是否有效
    /// </summary>
    bool IsValidLevel(string level);

    /// <summary>
    /// 取得所有等級列表
    /// </summary>
    IEnumerable<string> GetAllLevels();
}

/// <summary>
/// CEFR 等級服務實作
/// </summary>
public class CEFRLevelService : ICEFRLevelService
{
    private static readonly string[] Levels = { "A1", "A2", "B1", "B2", "C1", "C2" };
    private readonly ILogger<CEFRLevelService> _logger;

    public CEFRLevelService(ILogger<CEFRLevelService> logger)
    {
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public int GetLevelIndex(string level)
    {
        if (string.IsNullOrEmpty(level))
        {
            _logger.LogWarning("Invalid level provided: null or empty, defaulting to A2");
            return 1; // 預設 A2
        }

        var index = Array.IndexOf(Levels, level.ToUpper());
        if (index == -1)
        {
            _logger.LogWarning("Unknown CEFR level: {Level}, defaulting to A2", level);
            return 1;
        }

        return index;
    }

    public bool IsHighValueForUser(string wordLevel, string userLevel)
    {
        var userIndex = GetLevelIndex(userLevel);
        var wordIndex = GetLevelIndex(wordLevel);

        // 無效等級處理
        if (userIndex == -1 || wordIndex == -1)
        {
            _logger.LogWarning("Invalid levels for comparison: word={WordLevel}, user={UserLevel}", wordLevel, userLevel);
            return false;
        }

        // 高價值 = 比用戶程度高 1-2 級
        var isHighValue = wordIndex >= userIndex + 1 && wordIndex <= userIndex + 2;

        _logger.LogDebug("High value check: word={WordLevel}({WordIndex}), user={UserLevel}({UserIndex}), result={IsHighValue}",
            wordLevel, wordIndex, userLevel, userIndex, isHighValue);

        return isHighValue;
    }

    public string GetTargetLevelRange(string userLevel)
    {
        var userIndex = GetLevelIndex(userLevel);
        if (userIndex == -1) return "B1-B2";

        var targetMin = Levels[Math.Min(userIndex + 1, Levels.Length - 1)];
        var targetMax = Levels[Math.Min(userIndex + 2, Levels.Length - 1)];

        return targetMin == targetMax ? targetMin : $"{targetMin}-{targetMax}";
    }

    public string GetNextLevel(string currentLevel)
    {
        var currentIndex = GetLevelIndex(currentLevel);
        if (currentIndex == -1 || currentIndex >= Levels.Length - 1)
        {
            return Levels[^1]; // 返回最高等級
        }

        return Levels[currentIndex + 1];
    }

    public double CalculateLevelProgress(string currentLevel, int masteredWords, int totalWords)
    {
        if (totalWords == 0) return 0;

        var progress = (double)masteredWords / totalWords;
        _logger.LogDebug("Level progress for {Level}: {MasteredWords}/{TotalWords} = {Progress:P}",
            currentLevel, masteredWords, totalWords, progress);

        return Math.Min(progress, 1.0);
    }

    public string RecommendLevel(Dictionary<string, int> masteredWordsByLevel)
    {
        try
        {
            // 簡單的推薦邏輯：找到掌握詞彙最多的等級
            var bestLevel = masteredWordsByLevel
                .Where(kvp => kvp.Value > 0)
                .OrderByDescending(kvp => kvp.Value)
                .FirstOrDefault();

            if (bestLevel.Key != null && IsValidLevel(bestLevel.Key))
            {
                return GetNextLevel(bestLevel.Key);
            }

            return "A2"; // 預設等級
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error recommending level");
            return "A2";
        }
    }

    public bool IsValidLevel(string level)
    {
        return !string.IsNullOrEmpty(level) && Levels.Contains(level.ToUpper());
    }

    public IEnumerable<string> GetAllLevels()
    {
        return Levels.AsEnumerable();
    }
}