using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using DramaLing.Api.Services; namespace DramaLing.Api.Controllers; [ApiController] [Route("api/study/sessions")] [Authorize] public class StudySessionController : ControllerBase { private readonly IStudySessionService _studySessionService; private readonly IAuthService _authService; private readonly ILogger _logger; public StudySessionController( IStudySessionService studySessionService, IAuthService authService, ILogger logger) { _studySessionService = studySessionService; _authService = authService; _logger = logger; } /// /// 開始新的學習會話 /// [HttpPost("start")] public async Task StartSession() { try { var userId = await _authService.GetUserIdFromTokenAsync(Request.Headers.Authorization); if (userId == null) return Unauthorized(new { Success = false, Error = "Invalid token" }); var session = await _studySessionService.StartSessionAsync(userId.Value); return Ok(new { Success = true, Data = new { SessionId = session.Id, TotalCards = session.TotalCards, TotalTests = session.TotalTests, CurrentCardIndex = session.CurrentCardIndex, CurrentTestType = session.CurrentTestType, StartedAt = session.StartedAt }, Message = $"Study session started with {session.TotalCards} cards and {session.TotalTests} tests" }); } catch (InvalidOperationException ex) { return BadRequest(new { Success = false, Error = ex.Message }); } catch (Exception ex) { _logger.LogError(ex, "Error starting study session"); return StatusCode(500, new { Success = false, Error = "Failed to start study session", Timestamp = DateTime.UtcNow }); } } /// /// 獲取當前測驗 /// [HttpGet("{sessionId}/current-test")] public async Task GetCurrentTest(Guid sessionId) { try { var userId = await _authService.GetUserIdFromTokenAsync(Request.Headers.Authorization); if (userId == null) return Unauthorized(new { Success = false, Error = "Invalid token" }); var currentTest = await _studySessionService.GetCurrentTestAsync(sessionId); return Ok(new { Success = true, Data = currentTest }); } catch (InvalidOperationException ex) { return BadRequest(new { Success = false, Error = ex.Message }); } catch (Exception ex) { _logger.LogError(ex, "Error getting current test for session {SessionId}", sessionId); return StatusCode(500, new { Success = false, Error = "Failed to get current test", Timestamp = DateTime.UtcNow }); } } /// /// 提交測驗結果 /// [HttpPost("{sessionId}/submit-test")] public async Task SubmitTest(Guid sessionId, [FromBody] SubmitTestRequestDto 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.TestType)) { return BadRequest(new { Success = false, Error = "Test type is required" }); } if (request.ConfidenceLevel.HasValue && (request.ConfidenceLevel < 1 || request.ConfidenceLevel > 5)) { return BadRequest(new { Success = false, Error = "Confidence level must be between 1 and 5" }); } var response = await _studySessionService.SubmitTestAsync(sessionId, request); return Ok(new { Success = response.Success, Data = new { IsCardCompleted = response.IsCardCompleted, Progress = response.Progress }, Message = response.IsCardCompleted ? "Card completed!" : "Test recorded successfully" }); } catch (InvalidOperationException ex) { return BadRequest(new { Success = false, Error = ex.Message }); } catch (Exception ex) { _logger.LogError(ex, "Error submitting test for session {SessionId}", sessionId); return StatusCode(500, new { Success = false, Error = "Failed to submit test result", Timestamp = DateTime.UtcNow }); } } /// /// 獲取下一個測驗 /// [HttpGet("{sessionId}/next-test")] public async Task GetNextTest(Guid sessionId) { try { var userId = await _authService.GetUserIdFromTokenAsync(Request.Headers.Authorization); if (userId == null) return Unauthorized(new { Success = false, Error = "Invalid token" }); var nextTest = await _studySessionService.GetNextTestAsync(sessionId); return Ok(new { Success = true, Data = nextTest }); } catch (InvalidOperationException ex) { return BadRequest(new { Success = false, Error = ex.Message }); } catch (Exception ex) { _logger.LogError(ex, "Error getting next test for session {SessionId}", sessionId); return StatusCode(500, new { Success = false, Error = "Failed to get next test", Timestamp = DateTime.UtcNow }); } } /// /// 獲取詳細進度 /// [HttpGet("{sessionId}/progress")] public async Task GetProgress(Guid sessionId) { try { var userId = await _authService.GetUserIdFromTokenAsync(Request.Headers.Authorization); if (userId == null) return Unauthorized(new { Success = false, Error = "Invalid token" }); var progress = await _studySessionService.GetProgressAsync(sessionId); return Ok(new { Success = true, Data = progress }); } catch (InvalidOperationException ex) { return BadRequest(new { Success = false, Error = ex.Message }); } catch (Exception ex) { _logger.LogError(ex, "Error getting progress for session {SessionId}", sessionId); return StatusCode(500, new { Success = false, Error = "Failed to get progress", Timestamp = DateTime.UtcNow }); } } /// /// 完成學習會話 /// [HttpPut("{sessionId}/complete")] public async Task CompleteSession(Guid sessionId) { try { var userId = await _authService.GetUserIdFromTokenAsync(Request.Headers.Authorization); if (userId == null) return Unauthorized(new { Success = false, Error = "Invalid token" }); var session = await _studySessionService.CompleteSessionAsync(sessionId); return Ok(new { Success = true, Data = new { SessionId = session.Id, CompletedAt = session.EndedAt, TotalCards = session.TotalCards, CompletedCards = session.CompletedCards, TotalTests = session.TotalTests, CompletedTests = session.CompletedTests, DurationSeconds = session.DurationSeconds }, Message = "Study session completed successfully" }); } catch (InvalidOperationException ex) { return BadRequest(new { Success = false, Error = ex.Message }); } catch (Exception ex) { _logger.LogError(ex, "Error completing session {SessionId}", sessionId); return StatusCode(500, new { Success = false, Error = "Failed to complete session", Timestamp = DateTime.UtcNow }); } } }