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
};
}