namespace Extrudex.Domain.Interfaces;
///
/// Service interface for calculating the cost of goods sold (COGS) per print job.
/// Uses the spool's purchase price and the print job's derived grams consumed
/// to produce a cost breakdown. Handles missing cost data gracefully by returning
/// warnings rather than throwing exceptions.
///
public interface ICostPerPrintService
{
///
/// Calculates the cost per print for a specific print job.
///
/// The unique identifier of the print job.
/// Optional cancellation token.
///
/// A containing the cost breakdown,
/// or warnings if cost data is missing or incomplete.
///
Task CalculateAsync(Guid printJobId, CancellationToken cancellationToken = default);
///
/// Calculates cost breakdowns for all print jobs associated with a specific spool.
/// Useful for spool-level COGS reporting.
///
/// The unique identifier of the spool.
/// Optional cancellation token.
///
/// A list of for each print job on the spool.
/// Jobs with missing cost data will include warnings.
///
Task> CalculateBySpoolAsync(Guid spoolId, CancellationToken cancellationToken = default);
}
///
/// Result of a cost-per-print calculation. Contains the cost breakdown
/// and any warnings about missing or incomplete cost data.
///
public class CostPerPrintResult
{
/// The print job identifier this result belongs to.
public Guid PrintJobId { get; set; }
/// Human-readable name of the print job.
public string PrintName { get; set; } = string.Empty;
/// The spool identifier that provided filament.
public Guid SpoolId { get; set; }
/// Serial number of the spool.
public string SpoolSerial { get; set; } = string.Empty;
/// Total millimeters of filament extruded.
public decimal MmExtruded { get; set; }
/// Derived grams consumed for this print.
public decimal GramsDerived { get; set; }
/// The spool's purchase price. Null if not recorded.
public decimal? PurchasePrice { get; set; }
/// The spool's total weight in grams when full.
public decimal? WeightTotalGrams { get; set; }
/// Cost per gram of filament. Null if purchase price or total weight is missing.
public decimal? CostPerGram { get; set; }
/// Calculated cost of this print job. Null if cost data is incomplete.
public decimal? CostPerPrint { get; set; }
///
/// Warnings about missing or incomplete data that prevented a full calculation.
/// Empty when all data is available and the calculation succeeded.
///
public List Warnings { get; set; } = new();
}