dramaling-vocab-learning/backend/DramaLing.Api/Controllers/StudySessionController.cs

276 lines
9.2 KiB
C#

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<StudySessionController> _logger;
public StudySessionController(
IStudySessionService studySessionService,
IAuthService authService,
ILogger<StudySessionController> logger)
{
_studySessionService = studySessionService;
_authService = authService;
_logger = logger;
}
/// <summary>
/// 開始新的學習會話
/// </summary>
[HttpPost("start")]
public async Task<ActionResult> 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
});
}
}
/// <summary>
/// 獲取當前測驗
/// </summary>
[HttpGet("{sessionId}/current-test")]
public async Task<ActionResult> 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
});
}
}
/// <summary>
/// 提交測驗結果
/// </summary>
[HttpPost("{sessionId}/submit-test")]
public async Task<ActionResult> 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
});
}
}
/// <summary>
/// 獲取下一個測驗
/// </summary>
[HttpGet("{sessionId}/next-test")]
public async Task<ActionResult> 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
});
}
}
/// <summary>
/// 獲取詳細進度
/// </summary>
[HttpGet("{sessionId}/progress")]
public async Task<ActionResult> 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
});
}
}
/// <summary>
/// 完成學習會話
/// </summary>
[HttpPut("{sessionId}/complete")]
public async Task<ActionResult> 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
});
}
}
}