namespace Apollinare.Domain.Entities.Warehouse;

/// <summary>
/// Testata inventario fisico
/// </summary>
public class InventoryCount : BaseEntity
{
    /// <summary>
    /// Codice inventario
    /// </summary>
    public string Code { get; set; } = string.Empty;

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

    /// <summary>
    /// Data inventario
    /// </summary>
    public DateTime InventoryDate { get; set; }

    /// <summary>
    /// Magazzino (null = tutti i magazzini)
    /// </summary>
    public int? WarehouseId { get; set; }

    /// <summary>
    /// Categoria articoli (null = tutte)
    /// </summary>
    public int? CategoryId { get; set; }

    /// <summary>
    /// Tipo di inventario
    /// </summary>
    public InventoryType Type { get; set; } = InventoryType.Full;

    /// <summary>
    /// Stato inventario
    /// </summary>
    public InventoryStatus Status { get; set; } = InventoryStatus.Draft;

    /// <summary>
    /// Data inizio conteggio
    /// </summary>
    public DateTime? StartDate { get; set; }

    /// <summary>
    /// Data fine conteggio
    /// </summary>
    public DateTime? EndDate { get; set; }

    /// <summary>
    /// Data conferma
    /// </summary>
    public DateTime? ConfirmedDate { get; set; }

    /// <summary>
    /// Utente che ha confermato
    /// </summary>
    public string? ConfirmedBy { get; set; }

    /// <summary>
    /// ID movimento di rettifica generato
    /// </summary>
    public int? AdjustmentMovementId { get; set; }

    /// <summary>
    /// Valore differenze positive
    /// </summary>
    public decimal? PositiveDifferenceValue { get; set; }

    /// <summary>
    /// Valore differenze negative
    /// </summary>
    public decimal? NegativeDifferenceValue { get; set; }

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

    // Navigation properties
    public WarehouseLocation? Warehouse { get; set; }
    public WarehouseArticleCategory? Category { get; set; }
    public StockMovement? AdjustmentMovement { get; set; }
    public ICollection<InventoryCountLine> Lines { get; set; } = new List<InventoryCountLine>();
}

/// <summary>
/// Riga dettaglio inventario
/// </summary>
public class InventoryCountLine : BaseEntity
{
    /// <summary>
    /// Inventario padre
    /// </summary>
    public int InventoryCountId { get; set; }

    /// <summary>
    /// Articolo
    /// </summary>
    public int ArticleId { get; set; }

    /// <summary>
    /// Magazzino
    /// </summary>
    public int WarehouseId { get; set; }

    /// <summary>
    /// Partita (se gestito a lotti)
    /// </summary>
    public int? BatchId { get; set; }

    /// <summary>
    /// Ubicazione
    /// </summary>
    public string? LocationCode { get; set; }

    /// <summary>
    /// Quantità teorica (da sistema)
    /// </summary>
    public decimal TheoreticalQuantity { get; set; }

    /// <summary>
    /// Quantità contata
    /// </summary>
    public decimal? CountedQuantity { get; set; }

    /// <summary>
    /// Differenza = CountedQuantity - TheoreticalQuantity
    /// </summary>
    public decimal? Difference => CountedQuantity.HasValue
        ? CountedQuantity.Value - TheoreticalQuantity
        : null;

    /// <summary>
    /// Costo unitario per valorizzazione differenza
    /// </summary>
    public decimal? UnitCost { get; set; }

    /// <summary>
    /// Valore differenza
    /// </summary>
    public decimal? DifferenceValue => Difference.HasValue && UnitCost.HasValue
        ? Difference.Value * UnitCost.Value
        : null;

    /// <summary>
    /// Data/ora del conteggio
    /// </summary>
    public DateTime? CountedAt { get; set; }

    /// <summary>
    /// Utente che ha effettuato il conteggio
    /// </summary>
    public string? CountedBy { get; set; }

    /// <summary>
    /// Secondo conteggio (per verifica discrepanze)
    /// </summary>
    public decimal? SecondCountQuantity { get; set; }

    /// <summary>
    /// Utente secondo conteggio
    /// </summary>
    public string? SecondCountBy { get; set; }

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

    // Navigation properties
    public InventoryCount? InventoryCount { get; set; }
    public WarehouseArticle? Article { get; set; }
    public WarehouseLocation? Warehouse { get; set; }
    public ArticleBatch? Batch { get; set; }
}

/// <summary>
/// Tipo di inventario
/// </summary>
public enum InventoryType
{
    /// <summary>
    /// Inventario completo
    /// </summary>
    Full = 0,

    /// <summary>
    /// Inventario parziale (per categoria/ubicazione)
    /// </summary>
    Partial = 1,

    /// <summary>
    /// Inventario rotativo (ciclico)
    /// </summary>
    Cyclic = 2,

    /// <summary>
    /// Inventario a campione
    /// </summary>
    Sample = 3
}

/// <summary>
/// Stato dell'inventario
/// </summary>
public enum InventoryStatus
{
    /// <summary>
    /// Bozza
    /// </summary>
    Draft = 0,

    /// <summary>
    /// In corso
    /// </summary>
    InProgress = 1,

    /// <summary>
    /// Completato (in attesa conferma)
    /// </summary>
    Completed = 2,

    /// <summary>
    /// Confermato (rettifiche applicate)
    /// </summary>
    Confirmed = 3,

    /// <summary>
    /// Annullato
    /// </summary>
    Cancelled = 4
}
