using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using DramaLing.Api.Data;
using DramaLing.Api.Models.Entities;
using DramaLing.Api.Services;
using Microsoft.AspNetCore.Authorization;

namespace DramaLing.Api.Controllers;

[ApiController]
[Route("api/[controller]")]
[Authorize]
public class StudyController : ControllerBase
{
    private readonly DramaLingDbContext _context;
    private readonly IAuthService _authService;
    private readonly ILogger<StudyController> _logger;

    public StudyController(
        DramaLingDbContext context,
        IAuthService authService,
        ILogger<StudyController> logger)
    {
        _context = context;
        _authService = authService;
        _logger = logger;
    }

    /// <summary>
    /// 獲取待複習的詞卡 (支援 /frontend/app/learn/page.tsx)
    /// </summary>
    [HttpGet("due-cards")]
    public async Task<ActionResult> GetDueCards(
        [FromQuery] int limit = 50,
        [FromQuery] string? mode = null,
        [FromQuery] bool includeNew = true)
    {
        try
        {
            var userId = await _authService.GetUserIdFromTokenAsync(Request.Headers.Authorization);
            if (userId == null)
                return Unauthorized(new { Success = false, Error = "Invalid token" });

            var today = DateTime.Today;
            var query = _context.Flashcards
                .Include(f => f.CardSet)
                .Where(f => f.UserId == userId);

            // 篩選到期和新詞卡
            if (includeNew)
            {
                // 包含到期詞卡和新詞卡
                query = query.Where(f => f.NextReviewDate <= today || f.Repetitions == 0);
            }
            else
            {
                // 只包含到期詞卡
                query = query.Where(f => f.NextReviewDate <= today);
            }

            var dueCards = await query.Take(limit * 2).ToListAsync(); // 取更多用於排序

            // 計算優先級並排序
            var cardsWithPriority = dueCards.Select(card => new
            {
                Card = card,
                Priority = ReviewPriorityCalculator.CalculatePriority(
                    card.NextReviewDate,
                    card.EasinessFactor,
                    card.Repetitions
                ),
                IsDue = ReviewPriorityCalculator.ShouldReview(card.NextReviewDate),
                DaysOverdue = Math.Max(0, (today - card.NextReviewDate).Days)
            }).OrderByDescending(x => x.Priority).Take(limit);

            var result = cardsWithPriority.Select(x => new
            {
                x.Card.Id,
                x.Card.Word,
                x.Card.Translation,
                x.Card.Definition,
                x.Card.PartOfSpeech,
                x.Card.Pronunciation,
                x.Card.Example,
                x.Card.ExampleTranslation,
                x.Card.MasteryLevel,
                x.Card.NextReviewDate,
                x.Card.DifficultyLevel,
                CardSet = new
                {
                    x.Card.CardSet.Name,
                    x.Card.CardSet.Color
                },
                x.Priority,
                x.IsDue,
                x.DaysOverdue
            }).ToList();

            // 統計資訊
            var totalDue = await _context.Flashcards
                .Where(f => f.UserId == userId && f.NextReviewDate <= today)
                .CountAsync();

            var totalCards = await _context.Flashcards
                .Where(f => f.UserId == userId)
                .CountAsync();

            var newCards = await _context.Flashcards
                .Where(f => f.UserId == userId && f.Repetitions == 0)
                .CountAsync();

            return Ok(new
            {
                Success = true,
                Data = new
                {
                    Cards = result,
                    TotalDue = totalDue,
                    TotalCards = totalCards,
                    NewCards = newCards
                }
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error fetching due cards for user");
            return StatusCode(500, new
            {
                Success = false,
                Error = "Failed to fetch due cards",
                Timestamp = DateTime.UtcNow
            });
        }
    }

    /// <summary>
    /// 開始學習會話
    /// </summary>
    [HttpPost("sessions")]
    public async Task<ActionResult> CreateStudySession([FromBody] CreateStudySessionRequest request)
    {
        try
        {
            var userId = await _authService.GetUserIdFromTokenAsync(Request.Headers.Authorization);
            if (userId == null)
                return Unauthorized(new { Success = false, Error = "Invalid token" });

            // 基本驗證
            if (string.IsNullOrEmpty(request.Mode) ||
                !new[] { "flip", "quiz", "fill", "listening", "speaking" }.Contains(request.Mode))
            {
                return BadRequest(new { Success = false, Error = "Invalid study mode" });
            }

            if (request.CardIds == null || request.CardIds.Count == 0)
            {
                return BadRequest(new { Success = false, Error = "Card IDs are required" });
            }

            if (request.CardIds.Count > 50)
            {
                return BadRequest(new { Success = false, Error = "Cannot study more than 50 cards in one session" });
            }

            // 驗證詞卡是否屬於用戶
            var userCards = await _context.Flashcards
                .Where(f => f.UserId == userId && request.CardIds.Contains(f.Id))
                .CountAsync();

            if (userCards != request.CardIds.Count)
            {
                return BadRequest(new { Success = false, Error = "Some cards not found or not accessible" });
            }

            // 建立學習會話
            var session = new StudySession
            {
                Id = Guid.NewGuid(),
                UserId = userId.Value,
                SessionType = request.Mode,
                TotalCards = request.CardIds.Count,
                StartedAt = DateTime.UtcNow
            };

            _context.StudySessions.Add(session);
            await _context.SaveChangesAsync();

            // 獲取詞卡詳細資訊
            var cards = await _context.Flashcards
                .Include(f => f.CardSet)
                .Where(f => f.UserId == userId && request.CardIds.Contains(f.Id))
                .ToListAsync();

            // 按照請求的順序排列
            var orderedCards = request.CardIds
                .Select(id => cards.FirstOrDefault(c => c.Id == id))
                .Where(c => c != null)
                .ToList();

            return Ok(new
            {
                Success = true,
                Data = new
                {
                    SessionId = session.Id,
                    SessionType = request.Mode,
                    Cards = orderedCards.Select(c => new
                    {
                        c.Id,
                        c.Word,
                        c.Translation,
                        c.Definition,
                        c.PartOfSpeech,
                        c.Pronunciation,
                        c.Example,
                        c.ExampleTranslation,
                        c.MasteryLevel,
                        c.EasinessFactor,
                        c.Repetitions,
                        CardSet = new { c.CardSet.Name, c.CardSet.Color }
                    }),
                    TotalCards = orderedCards.Count,
                    StartedAt = session.StartedAt
                },
                Message = $"Study session started with {orderedCards.Count} cards"
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error creating study session");
            return StatusCode(500, new
            {
                Success = false,
                Error = "Failed to create study session",
                Timestamp = DateTime.UtcNow
            });
        }
    }

    /// <summary>
    /// 記錄學習結果 (支援 SM-2 算法)
    /// </summary>
    [HttpPost("sessions/{sessionId}/record")]
    public async Task<ActionResult> RecordStudyResult(
        Guid sessionId,
        [FromBody] RecordStudyResultRequest request)
    {
        try
        {
            var userId = await _authService.GetUserIdFromTokenAsync(Request.Headers.Authorization);
            if (userId == null)
                return Unauthorized(new { Success = false, Error = "Invalid token" });

            // 基本驗證
            if (request.QualityRating < 1 || request.QualityRating > 5)
            {
                return BadRequest(new { Success = false, Error = "Quality rating must be between 1 and 5" });
            }

            // 驗證學習會話
            var session = await _context.StudySessions
                .FirstOrDefaultAsync(s => s.Id == sessionId && s.UserId == userId);

            if (session == null)
            {
                return NotFound(new { Success = false, Error = "Study session not found" });
            }

            // 驗證詞卡
            var flashcard = await _context.Flashcards
                .FirstOrDefaultAsync(f => f.Id == request.FlashcardId && f.UserId == userId);

            if (flashcard == null)
            {
                return NotFound(new { Success = false, Error = "Flashcard not found" });
            }

            // 計算新的 SM-2 參數
            var sm2Input = new SM2Input(
                request.QualityRating,
                flashcard.EasinessFactor,
                flashcard.Repetitions,
                flashcard.IntervalDays
            );

            var sm2Result = SM2Algorithm.Calculate(sm2Input);

            // 記錄學習結果
            var studyRecord = new StudyRecord
            {
                Id = Guid.NewGuid(),
                UserId = userId.Value,
                FlashcardId = request.FlashcardId,
                SessionId = sessionId,
                StudyMode = session.SessionType,
                QualityRating = request.QualityRating,
                ResponseTimeMs = request.ResponseTimeMs,
                UserAnswer = request.UserAnswer,
                IsCorrect = request.IsCorrect,
                PreviousEasinessFactor = sm2Input.EasinessFactor,
                NewEasinessFactor = sm2Result.EasinessFactor,
                PreviousIntervalDays = sm2Input.IntervalDays,
                NewIntervalDays = sm2Result.IntervalDays,
                PreviousRepetitions = sm2Input.Repetitions,
                NewRepetitions = sm2Result.Repetitions,
                NextReviewDate = sm2Result.NextReviewDate,
                StudiedAt = DateTime.UtcNow
            };

            _context.StudyRecords.Add(studyRecord);

            // 更新詞卡的 SM-2 參數
            flashcard.EasinessFactor = sm2Result.EasinessFactor;
            flashcard.Repetitions = sm2Result.Repetitions;
            flashcard.IntervalDays = sm2Result.IntervalDays;
            flashcard.NextReviewDate = sm2Result.NextReviewDate;
            flashcard.MasteryLevel = SM2Algorithm.CalculateMastery(sm2Result.Repetitions, sm2Result.EasinessFactor);
            flashcard.TimesReviewed++;
            if (request.IsCorrect) flashcard.TimesCorrect++;
            flashcard.LastReviewedAt = DateTime.UtcNow;

            await _context.SaveChangesAsync();

            return Ok(new
            {
                Success = true,
                Data = new
                {
                    RecordId = studyRecord.Id,
                    NextReviewDate = sm2Result.NextReviewDate.ToString("yyyy-MM-dd"),
                    NewIntervalDays = sm2Result.IntervalDays,
                    NewMasteryLevel = flashcard.MasteryLevel,
                    EasinessFactor = sm2Result.EasinessFactor,
                    Repetitions = sm2Result.Repetitions,
                    QualityDescription = SM2Algorithm.GetQualityDescription(request.QualityRating)
                },
                Message = $"Study record saved. Next review in {sm2Result.IntervalDays} day(s)"
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error recording study result");
            return StatusCode(500, new
            {
                Success = false,
                Error = "Failed to record study result",
                Timestamp = DateTime.UtcNow
            });
        }
    }

    /// <summary>
    /// 完成學習會話
    /// </summary>
    [HttpPost("sessions/{sessionId}/complete")]
    public async Task<ActionResult> CompleteStudySession(
        Guid sessionId,
        [FromBody] CompleteStudySessionRequest request)
    {
        try
        {
            var userId = await _authService.GetUserIdFromTokenAsync(Request.Headers.Authorization);
            if (userId == null)
                return Unauthorized(new { Success = false, Error = "Invalid token" });

            // 驗證會話
            var session = await _context.StudySessions
                .FirstOrDefaultAsync(s => s.Id == sessionId && s.UserId == userId);

            if (session == null)
            {
                return NotFound(new { Success = false, Error = "Study session not found" });
            }

            // 計算會話統計
            var sessionRecords = await _context.StudyRecords
                .Where(r => r.SessionId == sessionId && r.UserId == userId)
                .ToListAsync();

            var correctCount = sessionRecords.Count(r => r.IsCorrect);
            var averageResponseTime = sessionRecords.Any(r => r.ResponseTimeMs.HasValue)
                ? (int)sessionRecords.Where(r => r.ResponseTimeMs.HasValue).Average(r => r.ResponseTimeMs!.Value)
                : 0;

            // 更新會話
            session.EndedAt = DateTime.UtcNow;
            session.CorrectCount = correctCount;
            session.DurationSeconds = request.DurationSeconds;
            session.AverageResponseTimeMs = averageResponseTime;

            // 更新或建立每日統計
            var today = DateOnly.FromDateTime(DateTime.Today);
            var dailyStats = await _context.DailyStats
                .FirstOrDefaultAsync(ds => ds.UserId == userId && ds.Date == today);

            if (dailyStats == null)
            {
                dailyStats = new DailyStats
                {
                    Id = Guid.NewGuid(),
                    UserId = userId.Value,
                    Date = today
                };
                _context.DailyStats.Add(dailyStats);
            }

            dailyStats.WordsStudied += sessionRecords.Count;
            dailyStats.WordsCorrect += correctCount;
            dailyStats.StudyTimeSeconds += request.DurationSeconds;
            dailyStats.SessionCount++;

            await _context.SaveChangesAsync();

            // 計算會話統計
            var accuracy = sessionRecords.Count > 0
                ? (int)Math.Round((double)correctCount / sessionRecords.Count * 100)
                : 0;

            var averageTimePerCard = request.DurationSeconds > 0 && sessionRecords.Count > 0
                ? request.DurationSeconds / sessionRecords.Count
                : 0;

            return Ok(new
            {
                Success = true,
                Data = new
                {
                    SessionId = sessionId,
                    TotalCards = session.TotalCards,
                    CardsStudied = sessionRecords.Count,
                    CorrectAnswers = correctCount,
                    AccuracyPercentage = accuracy,
                    DurationSeconds = request.DurationSeconds,
                    AverageTimePerCard = averageTimePerCard,
                    AverageResponseTimeMs = averageResponseTime,
                    StartedAt = session.StartedAt,
                    EndedAt = session.EndedAt
                },
                Message = $"Study session completed! {correctCount}/{sessionRecords.Count} correct ({accuracy}%)"
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error completing study session");
            return StatusCode(500, new
            {
                Success = false,
                Error = "Failed to complete study session",
                Timestamp = DateTime.UtcNow
            });
        }
    }

    /// <summary>
    /// 獲取智能複習排程
    /// </summary>
    [HttpGet("schedule")]
    public async Task<ActionResult> GetReviewSchedule(
        [FromQuery] bool includePlan = true,
        [FromQuery] bool includeStats = true)
    {
        try
        {
            var userId = await _authService.GetUserIdFromTokenAsync(Request.Headers.Authorization);
            if (userId == null)
                return Unauthorized(new { Success = false, Error = "Invalid token" });

            // 獲取用戶設定
            var settings = await _context.UserSettings
                .FirstOrDefaultAsync(s => s.UserId == userId);
            var dailyGoal = settings?.DailyGoal ?? 20;

            // 獲取所有詞卡
            var allCards = await _context.Flashcards
                .Where(f => f.UserId == userId)
                .ToListAsync();

            var today = DateTime.Today;

            // 分類詞卡
            var dueToday = allCards.Where(c => c.NextReviewDate == today).ToList();
            var overdue = allCards.Where(c => c.NextReviewDate < today && c.Repetitions > 0).ToList();
            var upcoming = allCards.Where(c => c.NextReviewDate > today && c.NextReviewDate <= today.AddDays(7)).ToList();
            var newCards = allCards.Where(c => c.Repetitions == 0).ToList();

            // 建立回應物件
            var responseData = new Dictionary<string, object>
            {
                ["Schedule"] = new
                {
                    DueToday = dueToday.Count,
                    Overdue = overdue.Count,
                    Upcoming = upcoming.Count,
                    NewCards = newCards.Count
                }
            };

            // 生成學習計劃
            if (includePlan)
            {
                var recommendedCards = overdue.Take(dailyGoal / 2)
                    .Concat(dueToday.Take(dailyGoal / 3))
                    .Concat(newCards.Take(Math.Min(5, dailyGoal / 4)))
                    .Take(dailyGoal)
                    .Select(c => new
                    {
                        c.Id,
                        c.Word,
                        c.Translation,
                        c.MasteryLevel,
                        c.NextReviewDate,
                        PriorityReason = c.Repetitions == 0 ? "new_card" :
                                       c.NextReviewDate < today ? "overdue" : "due_today"
                    });

                responseData["StudyPlan"] = new
                {
                    RecommendedCards = recommendedCards,
                    Breakdown = new
                    {
                        Overdue = Math.Min(overdue.Count, dailyGoal / 2),
                        DueToday = Math.Min(dueToday.Count, dailyGoal / 3),
                        NewCards = Math.Min(newCards.Count, 5)
                    },
                    EstimatedTimeMinutes = recommendedCards.Count() * 1,
                    DailyGoal = dailyGoal
                };
            }

            // 計算統計
            if (includeStats)
            {
                responseData["Statistics"] = new
                {
                    TotalCards = allCards.Count,
                    MasteredCards = allCards.Count(c => c.MasteryLevel >= 80),
                    LearningCards = allCards.Count(c => c.MasteryLevel >= 40 && c.MasteryLevel < 80),
                    NewCardsCount = newCards.Count,
                    AverageMastery = allCards.Count > 0 ? (int)allCards.Average(c => c.MasteryLevel) : 0,
                    RetentionRate = allCards.Count(c => c.Repetitions > 0) > 0
                        ? (int)Math.Round((double)allCards.Count(c => c.MasteryLevel >= 60) / allCards.Count(c => c.Repetitions > 0) * 100)
                        : 0
                };
            }

            return Ok(new
            {
                Success = true,
                Data = responseData
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error fetching review schedule");
            return StatusCode(500, new
            {
                Success = false,
                Error = "Failed to fetch review schedule",
                Timestamp = DateTime.UtcNow
            });
        }
    }
}

// Request DTOs
public class CreateStudySessionRequest
{
    public string Mode { get; set; } = string.Empty; // flip, quiz, fill, listening, speaking
    public List<Guid> CardIds { get; set; } = new();
}

public class RecordStudyResultRequest
{
    public Guid FlashcardId { get; set; }
    public int QualityRating { get; set; } // 1-5
    public int? ResponseTimeMs { get; set; }
    public string? UserAnswer { get; set; }
    public bool IsCorrect { get; set; }
}

public class CompleteStudySessionRequest
{
    public int DurationSeconds { get; set; }
}