using Extrudex.Domain.Base;

namespace Extrudex.Domain.Entities;

/// <summary>
/// Represents a physical spool of filament. Every spool must have a MaterialBase
/// and MaterialFinish. MaterialModifier is optional.
/// Spools are the core inventory unit and link to PrintJobs for COGS tracking.
/// </summary>
public class Spool : AuditableEntity
{
    /// <summary>
    /// Foreign key to the base material. Every spool must specify a material base.
    /// </summary>
    public Guid MaterialBaseId { get; set; }

    /// <summary>
    /// Navigation to the base material (e.g., PLA, PETG, ABS).
    /// </summary>
    public MaterialBase MaterialBase { get; set; } = null!;

    /// <summary>
    /// Foreign key to the material finish. REQUIRED on every spool — default is "Basic".
    /// </summary>
    public Guid MaterialFinishId { get; set; }

    /// <summary>
    /// Navigation to the material finish (e.g., Basic, Matte, Silk, Glitter).
    /// </summary>
    public MaterialFinish MaterialFinish { get; set; } = null!;

    /// <summary>
    /// Foreign key to the optional material modifier. Null if no modifier applies.
    /// </summary>
    public Guid? MaterialModifierId { get; set; }

    /// <summary>
    /// Navigation to the optional material modifier (e.g., Carbon Fiber, Wood Fill).
    /// </summary>
    public MaterialModifier? MaterialModifier { get; set; }

    /// <summary>
    /// Human-readable brand name (e.g., "Bambu Lab", "Polymaker", "eSUN").
    /// </summary>
    public string Brand { get; set; } = string.Empty;

    /// <summary>
    /// Human-readable color name (e.g., "Fire Engine Red", "Galaxy Black").
    /// </summary>
    public string ColorName { get; set; } = string.Empty;

    /// <summary>
    /// Hex color code for the filament (e.g., "#FF0000" for red).
    /// Enables color-based filtering and visual identification.
    /// </summary>
    public string ColorHex { get; set; } = string.Empty;

    /// <summary>
    /// Total spool weight in grams when full (brand new, unopened).
    /// </summary>
    public decimal WeightTotalGrams { get; set; }

    /// <summary>
    /// Current remaining weight in grams. Updated via AMS data or manual check-in.
    /// </summary>
    public decimal WeightRemainingGrams { get; set; }

    /// <summary>
    /// Filament diameter in millimeters. Typically 1.75mm for FDM printers.
    /// Used in the COGS derivation formula: grams = mm × cross_section_area × density.
    /// </summary>
    public decimal FilamentDiameterMm { get; set; } = 1.75m;

    /// <summary>
    /// Manufacturer-assigned serial number for the spool. Used for barcode/QR scanning.
    /// Must be unique across all spools.
    /// </summary>
    public string SpoolSerial { get; set; } = string.Empty;

    /// <summary>
    /// Purchase price per spool in the system currency. Used for COGS calculations.
    /// </summary>
    public decimal? PurchasePrice { get; set; }

    /// <summary>
    /// Date the spool was purchased or received.
    /// </summary>
    public DateTime? PurchaseDate { get; set; }

    /// <summary>
    /// Whether the spool is currently active and available for use.
    /// Inactive spools are retained for historical COGS records.
    /// </summary>
    public bool IsActive { get; set; } = true;

    /// <summary>
    /// Whether the spool has been archived (removed from active inventory).
    /// Archived spools are retained for historical records but hidden from
    /// default inventory views. Distinguishes long-term archival from
    /// temporary inactivity (e.g., spool swapped out of AMS).
    /// </summary>
    public bool IsArchived { get; set; } = false;

    /// <summary>
    /// Physical storage location of the spool (e.g., "Shelf A", "Drawer 3", "AMS Tray 2").
    /// Optional — not every spool has a designated storage location.
    /// </summary>
    public string? StorageLocation { get; set; }

    /// <summary>
    /// Navigation collection of AMS slots where this spool is loaded.
    /// </summary>
    public ICollection<AmsSlot> AmsSlots { get; set; } = new List<AmsSlot>();

    /// <summary>
    /// Navigation collection of print jobs that consumed filament from this spool.
    /// </summary>
    public ICollection<PrintJob> PrintJobs { get; set; } = new List<PrintJob>();

    /// <summary>
    /// Navigation collection of filament usage records tracking consumption from this spool.
    /// Enables querying how much filament was consumed per print job.
    /// </summary>
    public ICollection<FilamentUsage> FilamentUsages { get; set; } = new List<FilamentUsage>();
}