using DramaLing.Api.Data;
using DramaLing.Api.Models.Configuration;
using DramaLing.Api.Models.DTOs.SpacedRepetition;
using DramaLing.Api.Models.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using System.Text.Json;

namespace DramaLing.Api.Services;

/// <summary>
/// 智能複習題型選擇服務介面
/// </summary>
public interface IReviewTypeSelectorService
{
    Task<ReviewModeResult> SelectOptimalReviewModeAsync(Guid flashcardId, int userLevel, int wordLevel);
    string[] GetAvailableReviewTypes(int userLevel, int wordLevel);
    bool IsA1Learner(int userLevel);
    string GetAdaptationContext(int userLevel, int wordLevel);
}

/// <summary>
/// 智能複習題型選擇服務實現
/// </summary>
public class ReviewTypeSelectorService : IReviewTypeSelectorService
{
    private readonly DramaLingDbContext _context;
    private readonly ILogger<ReviewTypeSelectorService> _logger;
    private readonly SpacedRepetitionOptions _options;

    public ReviewTypeSelectorService(
        DramaLingDbContext context,
        ILogger<ReviewTypeSelectorService> logger,
        IOptions<SpacedRepetitionOptions> options)
    {
        _context = context;
        _logger = logger;
        _options = options.Value;
    }

    /// <summary>
    /// 智能選擇最適合的複習模式
    /// </summary>
    public async Task<ReviewModeResult> SelectOptimalReviewModeAsync(Guid flashcardId, int userLevel, int wordLevel)
    {
        _logger.LogInformation("Selecting optimal review mode for flashcard {FlashcardId}, userLevel: {UserLevel}, wordLevel: {WordLevel}",
            flashcardId, userLevel, wordLevel);

        // 1. 四情境判斷，獲取可用題型
        var availableModes = GetAvailableReviewTypes(userLevel, wordLevel);

        // 2. 檢查復習歷史，實現智能避重
        var filteredModes = await ApplyAntiRepetitionLogicAsync(flashcardId, availableModes);

        // 3. 智能選擇 (A1學習者權重選擇，其他隨機)
        var selectedMode = SelectModeWithWeights(filteredModes, userLevel);

        var adaptationContext = GetAdaptationContext(userLevel, wordLevel);
        var reason = GetSelectionReason(selectedMode, userLevel, wordLevel);

        _logger.LogInformation("Selected mode: {SelectedMode}, context: {Context}, reason: {Reason}",
            selectedMode, adaptationContext, reason);

        return new ReviewModeResult
        {
            SelectedMode = selectedMode,
            AvailableModes = availableModes,
            AdaptationContext = adaptationContext,
            Reason = reason
        };
    }

    /// <summary>
    /// 四情境自動適配：根據學習者程度和詞彙難度決定可用題型
    /// </summary>
    public string[] GetAvailableReviewTypes(int userLevel, int wordLevel)
    {
        var difficulty = wordLevel - userLevel;

        if (userLevel <= _options.A1ProtectionLevel)
        {
            // A1學習者 - 自動保護，只使用基礎題型
            return new[] { "flip-memory", "vocab-choice", "vocab-listening" };
        }

        if (difficulty < -10)
        {
            // 簡單詞彙 (學習者程度 > 詞彙程度) - 應用練習
            return new[] { "sentence-reorder", "sentence-fill" };
        }

        if (difficulty >= -10 && difficulty <= 10)
        {
            // 適中詞彙 (學習者程度 ≈ 詞彙程度) - 全方位練習
            return new[] { "sentence-fill", "sentence-reorder", "sentence-speaking" };
        }

        // 困難詞彙 (學習者程度 < 詞彙程度) - 基礎重建
        return new[] { "flip-memory", "vocab-choice" };
    }

    /// <summary>
    /// 智能避重邏輯：避免連續使用相同題型
    /// </summary>
    private async Task<string[]> ApplyAntiRepetitionLogicAsync(Guid flashcardId, string[] availableModes)
    {
        try
        {
            var flashcard = await _context.Flashcards.FindAsync(flashcardId);
            if (flashcard?.ReviewHistory == null)
                return availableModes;

            var history = JsonSerializer.Deserialize<List<ReviewRecord>>(flashcard.ReviewHistory) ?? new List<ReviewRecord>();
            var recentModes = history.TakeLast(3).Select(r => r.QuestionType).ToList();

            if (recentModes.Count >= 2 && recentModes.TakeLast(2).All(m => m == recentModes.Last()))
            {
                // 最近2次都是相同題型，避免使用
                var filteredModes = availableModes.Where(m => m != recentModes.Last()).ToArray();
                return filteredModes.Length > 0 ? filteredModes : availableModes;
            }

            return availableModes;
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Failed to apply anti-repetition logic for flashcard {FlashcardId}", flashcardId);
            return availableModes;
        }
    }

    /// <summary>
    /// 權重選擇模式 (A1學習者有權重，其他隨機)
    /// </summary>
    private string SelectModeWithWeights(string[] modes, int userLevel)
    {
        if (userLevel <= _options.A1ProtectionLevel)
        {
            // A1學習者權重分配
            var weights = new Dictionary<string, double>
            {
                { "flip-memory", 0.4 },        // 40% - 主要熟悉方式
                { "vocab-choice", 0.4 },       // 40% - 概念強化
                { "vocab-listening", 0.2 }     // 20% - 發音練習
            };

            return WeightedRandomSelect(modes, weights);
        }

        // 其他情況隨機選擇
        var random = new Random();
        return modes[random.Next(modes.Length)];
    }

    /// <summary>
    /// 權重隨機選擇
    /// </summary>
    private string WeightedRandomSelect(string[] items, Dictionary<string, double> weights)
    {
        var totalWeight = items.Sum(item => weights.GetValueOrDefault(item, 1.0 / items.Length));
        var random = new Random().NextDouble() * totalWeight;

        foreach (var item in items)
        {
            var weight = weights.GetValueOrDefault(item, 1.0 / items.Length);
            random -= weight;
            if (random <= 0)
                return item;
        }

        return items[0]; // 備用返回
    }

    /// <summary>
    /// 判斷是否為A1學習者
    /// </summary>
    public bool IsA1Learner(int userLevel) => userLevel <= _options.A1ProtectionLevel;

    /// <summary>
    /// 獲取適配情境描述
    /// </summary>
    public string GetAdaptationContext(int userLevel, int wordLevel)
    {
        var difficulty = wordLevel - userLevel;

        if (userLevel <= _options.A1ProtectionLevel)
            return "A1學習者";

        if (difficulty < -10)
            return "簡單詞彙";

        if (difficulty >= -10 && difficulty <= 10)
            return "適中詞彙";

        return "困難詞彙";
    }

    /// <summary>
    /// 獲取選擇原因說明
    /// </summary>
    private string GetSelectionReason(string selectedMode, int userLevel, int wordLevel)
    {
        var context = GetAdaptationContext(userLevel, wordLevel);

        return context switch
        {
            "A1學習者" => "A1學習者使用基礎題型建立信心",
            "簡單詞彙" => "簡單詞彙重點練習應用和拼寫",
            "適中詞彙" => "適中詞彙進行全方位練習",
            "困難詞彙" => "困難詞彙回歸基礎重建記憶",
            _ => "系統智能選擇"
        };
    }
}

/// <summary>
/// 復習記錄 (用於ReviewHistory JSON序列化)
/// </summary>
public record ReviewRecord(string QuestionType, bool IsCorrect, DateTime Date);