namespace Apollinare.Domain.Entities.Warehouse;

/// <summary>
/// Articolo del modulo magazzino con gestione completa di partite e seriali
/// </summary>
public class WarehouseArticle : BaseEntity
{
    /// <summary>
    /// Codice univoco articolo (SKU) - generato automaticamente
    /// </summary>
    public string Code { get; set; } = string.Empty;

    /// <summary>
    /// Codice alternativo (opzionale, inserito dall'utente)
    /// </summary>
    public string? AlternativeCode { get; set; }

    /// <summary>
    /// Descrizione articolo
    /// </summary>
    public string Description { get; set; } = string.Empty;

    /// <summary>
    /// Descrizione breve per etichette
    /// </summary>
    public string? ShortDescription { get; set; }

    /// <summary>
    /// Codice a barre principale (EAN/UPC)
    /// </summary>
    public string? Barcode { get; set; }

    /// <summary>
    /// Codice fornitore/produttore
    /// </summary>
    public string? ManufacturerCode { get; set; }

    /// <summary>
    /// Categoria articolo
    /// </summary>
    public int? CategoryId { get; set; }

    /// <summary>
    /// Unità di misura principale (es. PZ, KG, LT, MT)
    /// </summary>
    public string UnitOfMeasure { get; set; } = "PZ";

    /// <summary>
    /// Unità di misura secondaria per conversione
    /// </summary>
    public string? SecondaryUnitOfMeasure { get; set; }

    /// <summary>
    /// Fattore di conversione tra UoM primaria e secondaria
    /// </summary>
    public decimal? UnitConversionFactor { get; set; }

    /// <summary>
    /// Tipo di gestione magazzino
    /// </summary>
    public StockManagementType StockManagement { get; set; } = StockManagementType.Standard;

    /// <summary>
    /// Se true, l'articolo è gestito a partite (lotti)
    /// </summary>
    public bool IsBatchManaged { get; set; }

    /// <summary>
    /// Se true, l'articolo è gestito a seriali
    /// </summary>
    public bool IsSerialManaged { get; set; }

    /// <summary>
    /// Se true, l'articolo ha scadenza
    /// </summary>
    public bool HasExpiry { get; set; }

    /// <summary>
    /// Giorni di preavviso scadenza
    /// </summary>
    public int? ExpiryWarningDays { get; set; }

    /// <summary>
    /// Scorta minima (sotto questo livello scatta alert)
    /// </summary>
    public decimal? MinimumStock { get; set; }

    /// <summary>
    /// Scorta massima
    /// </summary>
    public decimal? MaximumStock { get; set; }

    /// <summary>
    /// Punto di riordino
    /// </summary>
    public decimal? ReorderPoint { get; set; }

    /// <summary>
    /// Quantità di riordino standard
    /// </summary>
    public decimal? ReorderQuantity { get; set; }

    /// <summary>
    /// Lead time in giorni per approvvigionamento
    /// </summary>
    public int? LeadTimeDays { get; set; }

    /// <summary>
    /// Metodo di valorizzazione per questo articolo (override del default)
    /// </summary>
    public ValuationMethod? ValuationMethod { get; set; }

    /// <summary>
    /// Costo standard (per valorizzazione a costo standard)
    /// </summary>
    public decimal? StandardCost { get; set; }

    /// <summary>
    /// Ultimo costo di acquisto
    /// </summary>
    public decimal? LastPurchaseCost { get; set; }

    /// <summary>
    /// Costo medio ponderato corrente
    /// </summary>
    public decimal? WeightedAverageCost { get; set; }

    /// <summary>
    /// Prezzo di vendita base
    /// </summary>
    public decimal? BaseSellingPrice { get; set; }

    /// <summary>
    /// Peso in Kg
    /// </summary>
    public decimal? Weight { get; set; }

    /// <summary>
    /// Volume in metri cubi
    /// </summary>
    public decimal? Volume { get; set; }

    /// <summary>
    /// Larghezza in cm
    /// </summary>
    public decimal? Width { get; set; }

    /// <summary>
    /// Altezza in cm
    /// </summary>
    public decimal? Height { get; set; }

    /// <summary>
    /// Profondità in cm
    /// </summary>
    public decimal? Depth { get; set; }

    /// <summary>
    /// Immagine principale
    /// </summary>
    public byte[]? Image { get; set; }

    /// <summary>
    /// Mime type immagine
    /// </summary>
    public string? ImageMimeType { get; set; }

    /// <summary>
    /// Se attivo, l'articolo può essere movimentato
    /// </summary>
    public bool IsActive { get; set; } = true;

    /// <summary>
    /// Note aggiuntive
    /// </summary>
    public string? Notes { get; set; }

    // Navigation properties
    public WarehouseArticleCategory? Category { get; set; }
    public ICollection<StockLevel> StockLevels { get; set; } = new List<StockLevel>();
    public ICollection<StockMovementLine> MovementLines { get; set; } = new List<StockMovementLine>();
    public ICollection<ArticleBatch> Batches { get; set; } = new List<ArticleBatch>();
    public ICollection<ArticleSerial> Serials { get; set; } = new List<ArticleSerial>();
    public ICollection<ArticleBarcode> Barcodes { get; set; } = new List<ArticleBarcode>();
}

/// <summary>
/// Tipo di gestione magazzino per l'articolo
/// </summary>
public enum StockManagementType
{
    /// <summary>
    /// Gestione standard (quantità)
    /// </summary>
    Standard = 0,

    /// <summary>
    /// Non gestito a magazzino (servizi, ecc.)
    /// </summary>
    NotManaged = 1,

    /// <summary>
    /// Gestione a peso variabile
    /// </summary>
    VariableWeight = 2,

    /// <summary>
    /// Kit/Distinta base
    /// </summary>
    Kit = 3
}

/// <summary>
/// Metodo di valorizzazione magazzino
/// </summary>
public enum ValuationMethod
{
    /// <summary>
    /// Costo medio ponderato
    /// </summary>
    WeightedAverage = 0,

    /// <summary>
    /// First In First Out
    /// </summary>
    FIFO = 1,

    /// <summary>
    /// Last In First Out
    /// </summary>
    LIFO = 2,

    /// <summary>
    /// Costo standard
    /// </summary>
    StandardCost = 3,

    /// <summary>
    /// Costo specifico (per partita/seriale)
    /// </summary>
    SpecificCost = 4
}
