using FluentValidation; using Microsoft.AspNetCore.Mvc; using SIGCM2.Application.Abstractions; using SIGCM2.Application.Auth.Login; namespace SIGCM2.Api.Controllers; [ApiController] [Route("api/v1/auth")] public sealed class AuthController : ControllerBase { private readonly IDispatcher _dispatcher; private readonly IValidator _validator; public AuthController(IDispatcher dispatcher, IValidator validator) { _dispatcher = dispatcher; _validator = validator; } /// Authenticates a user and returns a JWT access token. /// Returns access token and refresh token. /// Validation error — missing or empty fields. /// Invalid credentials. [HttpPost("login")] [ProducesResponseType(typeof(LoginResponseDto), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task Login([FromBody] LoginRequest request) { var command = new LoginCommand(request.Username ?? string.Empty, request.Password ?? string.Empty); var validation = await _validator.ValidateAsync(command); if (!validation.IsValid) { var errors = validation.Errors .GroupBy(e => e.PropertyName) .ToDictionary(g => g.Key, g => g.Select(e => e.ErrorMessage).ToArray()); return BadRequest(new { errors }); } var result = await _dispatcher.Send(command); return Ok(result); } } /// Login request body — nullable to catch missing field scenarios. public sealed record LoginRequest(string? Username, string? Password);