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

174 lines
5.8 KiB
C#

using DramaLing.Api.Models.DTOs;
using DramaLing.Api.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
namespace DramaLing.Api.Controllers;
[Route("api/[controller]")]
[Authorize]
public class ImageGenerationController : BaseController
{
private readonly IImageGenerationOrchestrator _orchestrator;
public ImageGenerationController(
IImageGenerationOrchestrator orchestrator,
ILogger<ImageGenerationController> logger) : base(logger)
{
_orchestrator = orchestrator ?? throw new ArgumentNullException(nameof(orchestrator));
}
/// <summary>
/// 為指定詞卡生成例句圖片
/// </summary>
/// <param name="flashcardId">詞卡 ID</param>
/// <param name="request">生成請求參數</param>
/// <returns>生成請求結果</returns>
[HttpPost("flashcards/{flashcardId}/generate")]
public async Task<IActionResult> GenerateImage(
Guid flashcardId,
[FromBody] GenerationRequest request)
{
try
{
var userId = GetCurrentUserId();
request.UserId = userId;
_logger.LogInformation("Starting image generation for flashcard {FlashcardId} by user {UserId}",
flashcardId, userId);
var result = await _orchestrator.StartGenerationAsync(flashcardId, request);
return SuccessResponse(result);
}
catch (ArgumentException ex)
{
_logger.LogWarning(ex, "Invalid request for flashcard {FlashcardId}", flashcardId);
return ErrorResponse("INVALID_REQUEST", ex.Message, null, 400);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to start image generation for flashcard {FlashcardId}", flashcardId);
return ErrorResponse("GENERATION_FAILED", "Failed to start generation");
}
}
/// <summary>
/// 獲取圖片生成狀態
/// </summary>
/// <param name="requestId">生成請求 ID</param>
/// <returns>生成狀態詳情</returns>
[HttpGet("requests/{requestId}/status")]
public async Task<IActionResult> GetGenerationStatus(Guid requestId)
{
try
{
var userId = GetCurrentUserId();
_logger.LogInformation("Getting generation status for request {RequestId} by user {UserId}",
requestId, userId);
var status = await _orchestrator.GetGenerationStatusAsync(requestId);
return SuccessResponse(status);
}
catch (ArgumentException ex)
{
_logger.LogWarning(ex, "Generation request {RequestId} not found", requestId);
return ErrorResponse("NOT_FOUND", ex.Message, null, 404);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to get status for request {RequestId}", requestId);
return ErrorResponse("STATUS_ERROR", "Failed to get status");
}
}
/// <summary>
/// 取消圖片生成請求
/// </summary>
/// <param name="requestId">生成請求 ID</param>
/// <returns>取消結果</returns>
[HttpPost("requests/{requestId}/cancel")]
public async Task<IActionResult> CancelGeneration(Guid requestId)
{
try
{
var userId = GetCurrentUserId();
_logger.LogInformation("Cancelling generation request {RequestId} by user {UserId}",
requestId, userId);
var cancelled = await _orchestrator.CancelGenerationAsync(requestId);
if (cancelled)
{
return SuccessResponse(new { message = "Generation cancelled successfully" });
}
else
{
return ErrorResponse("CANCEL_FAILED", "Cannot cancel this request", null, 400);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to cancel generation request {RequestId}", requestId);
return ErrorResponse("CANCEL_ERROR", "Failed to cancel generation");
}
}
/// <summary>
/// 獲取用戶的圖片生成歷史
/// </summary>
/// <param name="page">頁碼</param>
/// <param name="pageSize">每頁數量</param>
/// <returns>生成歷史列表</returns>
[HttpGet("history")]
public async Task<IActionResult> GetGenerationHistory(
[FromQuery] int page = 1,
[FromQuery] int pageSize = 20)
{
try
{
var userId = GetCurrentUserId();
// TODO: 實現分頁查詢邏輯
// 暫時返回空列表
var history = new
{
requests = new List<object>(),
pagination = new
{
currentPage = page,
pageSize = pageSize,
totalCount = 0,
totalPages = 0
}
};
return SuccessResponse(history);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to get generation history for user");
return ErrorResponse("HISTORY_ERROR", "Failed to get history");
}
}
private Guid GetCurrentUserId()
{
var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier)?.Value
?? User.FindFirst("sub")?.Value;
if (string.IsNullOrEmpty(userIdClaim))
{
throw new UnauthorizedAccessException("User ID not found in token");
}
if (!Guid.TryParse(userIdClaim, out var userId))
{
throw new UnauthorizedAccessException("Invalid user ID format in token");
}
return userId;
}
}