using GermanApp.Domain.Interfaces; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace GermanApp.Presentation.Controllers; /// /// API controller for Mistral AI text generation. /// This is part of the Presentation layer. /// [ApiController] [Route("api/[controller]")] [Authorize] public class MistralController : ControllerBase { private readonly IMistralService _mistralService; public MistralController(IMistralService mistralService) { _mistralService = mistralService; } /// /// Generates text from a prompt. /// /// Text generation request /// Cancellation token /// Generated text [HttpPost("generate")] public async Task GenerateText( [FromBody] TextGenerationRequest request, CancellationToken cancellationToken = default) { if (string.IsNullOrWhiteSpace(request.Prompt)) return BadRequest("Prompt is required"); try { var result = await _mistralService.GenerateTextAsync( request.Prompt, request.Model, request.Temperature, request.MaxTokens, cancellationToken); return Ok(new TextGenerationResponse(result)); } catch (Exception ex) { return StatusCode(500, new { Error = ex.Message }); } } /// /// Generates text from chat messages. /// /// Chat generation request /// Cancellation token /// Generated text [HttpPost("chat")] public async Task GenerateChat( [FromBody] ChatGenerationRequest request, CancellationToken cancellationToken = default) { if (request.Messages == null || request.Messages.Count == 0) return BadRequest("Messages are required"); try { var result = await _mistralService.GenerateChatAsync( request.Messages, request.Model, request.Temperature, request.MaxTokens, cancellationToken); return Ok(new TextGenerationResponse(result)); } catch (Exception ex) { return StatusCode(500, new { Error = ex.Message }); } } /// /// Generates a story based on lesson context. /// /// Story generation request /// Cancellation token /// Generated story [HttpPost("story")] public async Task GenerateStory( [FromBody] StoryGenerationRequest request, CancellationToken cancellationToken = default) { if (string.IsNullOrWhiteSpace(request.Level)) return BadRequest("Level is required"); try { var result = await _mistralService.GenerateStoryAsync( request.Level, request.Topic ?? string.Empty, request.VocabularyWords ?? new List(), request.Length, cancellationToken); return Ok(new StoryGenerationResponse(result)); } catch (Exception ex) { return StatusCode(500, new { Error = ex.Message }); } } /// /// Provides feedback on user writing. /// /// Writing feedback request /// Cancellation token /// Generated feedback [HttpPost("writing-feedback")] public async Task GenerateWritingFeedback( [FromBody] WritingFeedbackRequest request, CancellationToken cancellationToken = default) { if (string.IsNullOrWhiteSpace(request.UserText)) return BadRequest("User text is required"); if (string.IsNullOrWhiteSpace(request.Level)) return BadRequest("Level is required"); try { var result = await _mistralService.GenerateWritingFeedbackAsync( request.UserText, request.Level, request.Prompt, cancellationToken); return Ok(new WritingFeedbackResponse(result)); } catch (Exception ex) { return StatusCode(500, new { Error = ex.Message }); } } /// /// Tests the Mistral API connection. /// /// Health check result [HttpGet("health")] [AllowAnonymous] public async Task HealthCheck(CancellationToken cancellationToken = default) { try { var isHealthy = await _mistralService.TestConnectionAsync(cancellationToken); return Ok(new { Healthy = isHealthy }); } catch (Exception ex) { return StatusCode(500, new { Error = ex.Message }); } } } /// /// Request DTO for text generation. /// public record TextGenerationRequest( string Prompt, string? Model = null, float Temperature = 0.7f, int? MaxTokens = null); /// /// Request DTO for chat generation. /// public record ChatGenerationRequest( IReadOnlyList<(string Role, string Content)> Messages, string? Model = null, float Temperature = 0.7f, int? MaxTokens = null); /// /// Request DTO for story generation. /// public record StoryGenerationRequest( string Level, string? Topic = null, IReadOnlyList? VocabularyWords = null, int Length = 200); /// /// Request DTO for writing feedback. /// public record WritingFeedbackRequest( string UserText, string Level, string? Prompt = null); /// /// Response DTO for text generation. /// public record TextGenerationResponse(string Text); /// /// Response DTO for story generation. /// public record StoryGenerationResponse(string Story); /// /// Response DTO for writing feedback. /// public record WritingFeedbackResponse(string Feedback);