using Microsoft.AspNetCore.Mvc; using RobotNet10.FleetManager.Services; using RobotNet10.FleetManager.Shared.DTOs.Responses; namespace RobotNet10.FleetManager.Controllers; /// /// API controller for managing robot model images /// [ApiController] [Route("api/robot-models/{robotModelId}/image")] public class RobotModelImagesController( IRobotModelImageStorageService imageStorageService, IRobotModelService robotModelService, Services.Logger logger) : ControllerBase { private readonly IRobotModelImageStorageService _imageStorageService = imageStorageService; private readonly IRobotModelService _robotModelService = robotModelService; private readonly Services.Logger _logger = logger; private const long MaxFileSize = 10 * 1024 * 1024; // 10MB /// /// Get robot model image /// [HttpGet] [ProducesResponseType(typeof(FileResult), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetImage(Guid robotModelId) { try { // Verify robot model exists var model = await _robotModelService.GetByIdAsync(robotModelId); if (model == null) { return NotFound(new ErrorResponseDto { Error = $"Robot model with ID {robotModelId} not found." }); } var imageStream = await _imageStorageService.GetImageAsync(robotModelId); if (imageStream == null) { return NotFound(new ErrorResponseDto { Error = $"Image for robot model {robotModelId} not found." }); } return File(imageStream, "image/png", $"{robotModelId}.png"); } catch (Exception ex) { _logger.Error($"Error getting image for robot model {robotModelId}: {ex.Message}"); return StatusCode(500, new ErrorResponseDto { Error = "An error occurred while retrieving the image." }); } } /// /// Upload robot model image /// [HttpPost] [RequestSizeLimit(MaxFileSize)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task UploadImage(Guid robotModelId, IFormFile file) { try { // Verify robot model exists var model = await _robotModelService.GetByIdAsync(robotModelId); if (model == null) { return NotFound(new ErrorResponseDto { Error = $"Robot model with ID {robotModelId} not found." }); } // Validate file if (file == null || file.Length == 0) { return BadRequest(new ErrorResponseDto { Error = "No file provided." }); } if (file.Length > MaxFileSize) { return BadRequest(new ErrorResponseDto { Error = $"File size exceeds maximum allowed size of {MaxFileSize / (1024 * 1024)}MB." }); } // Validate file extension var extension = Path.GetExtension(file.FileName).ToLowerInvariant(); if (extension != ".png") { return BadRequest(new ErrorResponseDto { Error = "Only PNG files are allowed." }); } // Read image dimensions using (var stream = file.OpenReadStream()) { var (width, height) = await _imageStorageService.GetImageDimensionsAsync(stream); // Save image stream.Position = 0; await _imageStorageService.SaveImageAsync(robotModelId, stream); // Update robot model with image dimensions await _robotModelService.UpdateAsync(robotModelId, new Shared.DTOs.RobotModel.UpdateRobotModelRequest { ImageWidth = width, ImageHeight = height }); } return Ok(new { Error = "Image uploaded successfully." }); } catch (InvalidOperationException ex) { return BadRequest(new ErrorResponseDto { Error = ex.Message }); } catch (KeyNotFoundException ex) { return NotFound(new ErrorResponseDto { Error = ex.Message }); } catch (Exception ex) { _logger.Error($"Error uploading image for robot model {robotModelId}: {ex.Message}"); return StatusCode(500, new ErrorResponseDto { Error = "An error occurred while uploading the image." }); } } /// /// Delete robot model image /// [HttpDelete] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task DeleteImage(Guid robotModelId) { try { // Verify robot model exists var model = await _robotModelService.GetByIdAsync(robotModelId); if (model == null) { return NotFound(new ErrorResponseDto { Error = $"Robot model with ID {robotModelId} not found." }); } var deleted = await _imageStorageService.DeleteImageAsync(robotModelId); if (!deleted) { return NotFound(new ErrorResponseDto { Error = $"Image for robot model {robotModelId} not found." }); } return NoContent(); } catch (Exception ex) { _logger.Error($"Error deleting image for robot model {robotModelId}: {ex.Message}"); return StatusCode(500, new ErrorResponseDto { Error = "An error occurred while deleting the image." }); } } }