using Extrudex.API.DTOs.UsageLogs; using Extrudex.Domain.Enums; using Extrudex.Domain.Interfaces; using Microsoft.AspNetCore.Mvc; namespace Extrudex.API.Controllers; /// /// API controller for recording and querying filament usage logs. /// Usage logs provide a fine-grained audit trail of filament consumption /// from printer integrations or manual input. /// [ApiController] [Route("api/[controller]")] [Produces("application/json")] public class UsageLogsController : ControllerBase { private readonly IUsageLogService _usageLogService; /// /// Initializes a new instance of the class. /// /// The usage log service for recording and querying usage. public UsageLogsController(IUsageLogService usageLogService) { _usageLogService = usageLogService; } /// /// Records a new filament usage entry. /// /// The usage entry details. /// The created usage log entry. [HttpPost] [ProducesResponseType(typeof(UsageLogResponse), StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public async Task> Create([FromBody] CreateUsageLogRequest request) { if (!Enum.TryParse(request.DataSource, ignoreCase: true, out var dataSource)) { return BadRequest($"Invalid data source: '{request.DataSource}'. Valid values: Mqtt, Moonraker, Manual."); } var entry = await _usageLogService.RecordUsageAsync( spoolId: request.SpoolId, gramsUsed: request.GramsUsed, dataSource: dataSource, printerId: request.PrinterId, printJobId: request.PrintJobId, mmExtruded: request.MmExtruded, usageTimestamp: request.UsageTimestamp, notes: request.Notes ); return CreatedAtAction( nameof(GetBySpool), new { spoolId = entry.SpoolId }, MapToResponse(entry)); } /// /// Gets usage logs for a specific spool, ordered by most recent first. /// /// The spool ID to filter by. /// A collection of usage log entries for the spool. [HttpGet("spool/{spoolId:guid}")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] public async Task>> GetBySpool(Guid spoolId) { var logs = await _usageLogService.GetBySpoolAsync(spoolId); return Ok(logs.Select(MapToResponse)); } /// /// Gets usage logs for a specific printer, ordered by most recent first. /// /// The printer ID to filter by. /// A collection of usage log entries for the printer. [HttpGet("printer/{printerId:guid}")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] public async Task>> GetByPrinter(Guid printerId) { var logs = await _usageLogService.GetByPrinterAsync(printerId); return Ok(logs.Select(MapToResponse)); } /// /// Gets usage logs for a specific print job, ordered by most recent first. /// /// The print job ID to filter by. /// A collection of usage log entries for the print job. [HttpGet("print-job/{printJobId:guid}")] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] public async Task>> GetByPrintJob(Guid printJobId) { var logs = await _usageLogService.GetByPrintJobAsync(printJobId); return Ok(logs.Select(MapToResponse)); } /// /// Maps a UsageLog domain entity to a UsageLogResponse DTO. /// private static UsageLogResponse MapToResponse(Domain.Entities.UsageLog log) => new() { Id = log.Id, SpoolId = log.SpoolId, PrinterId = log.PrinterId, PrintJobId = log.PrintJobId, GramsUsed = log.GramsUsed, MmExtruded = log.MmExtruded, UsageTimestamp = log.UsageTimestamp, DataSource = log.DataSource.ToString(), Notes = log.Notes, CreatedAt = log.CreatedAt, UpdatedAt = log.UpdatedAt }; }