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 logger) : base(logger) { _orchestrator = orchestrator ?? throw new ArgumentNullException(nameof(orchestrator)); } /// /// 為指定詞卡生成例句圖片 /// /// 詞卡 ID /// 生成請求參數 /// 生成請求結果 [HttpPost("flashcards/{flashcardId}/generate")] public async Task 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"); } } /// /// 獲取圖片生成狀態 /// /// 生成請求 ID /// 生成狀態詳情 [HttpGet("requests/{requestId}/status")] public async Task 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"); } } /// /// 取消圖片生成請求 /// /// 生成請求 ID /// 取消結果 [HttpPost("requests/{requestId}/cancel")] public async Task 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"); } } /// /// 獲取用戶的圖片生成歷史 /// /// 頁碼 /// 每頁數量 /// 生成歷史列表 [HttpGet("history")] public async Task GetGenerationHistory( [FromQuery] int page = 1, [FromQuery] int pageSize = 20) { try { var userId = GetCurrentUserId(); // TODO: 實現分頁查詢邏輯 // 暫時返回空列表 var history = new { requests = new List(), 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; } }