using AyCode.Core.Serializers.Attributes;
using AyCode.Core.Serializers.Toons;
using FruitBank.Common.Enums;
using LinqToDB.Mapping;
using Mango.Nop.Core.Entities;

namespace FruitBank.Common.Entities;

[AcBinarySerializable(false, true, false, true, false, false)]
[Table(Name = FruitBankConstClient.PreOrderItemDbTableName)]
[System.ComponentModel.DataAnnotations.Schema.Table(FruitBankConstClient.PreOrderItemDbTableName)]
[ToonDescription("Single product line of a customer preorder with fulfilment tracking", Purpose = "A requested product line within a PreOrder. Tracks requested versus cumulatively fulfilled quantity as incoming stock is allocated across one or more shipping-document conversion runs.")]
public sealed class PreOrderItem : MgEntityBase
{
    [ToonDescription(Purpose = "FK to the parent PreOrder.")]
    public int PreOrderId { get; set; }

    [ToonDescription(Purpose = "FK to the nopCommerce Product being preordered.")]
    public int ProductId { get; set; }

    [ToonDescription(Purpose = "Quantity of the product the customer requested.", Constraints = "positive")]
    public int RequestedQuantity { get; set; }

    [ToonDescription(Purpose = "Quantity allocated from incoming stock so far; accumulates across conversion runs until it reaches RequestedQuantity.", 
        BusinessRule = "this >= 0 && this <= RequestedQuantity")]
    public int FulfilledQuantity { get; set; }

    [ToonDescription(Purpose = "Gross unit price locked at preorder time. Used as the order-item price on conversion for non-measurable products; measurable products are priced 0 at conversion and weighed afterwards.",
        Constraints = "non-negative")]
    public decimal UnitPriceInclTax { get; set; }

    // Persisted as an int column ("Status"). A raw enum property is NOT mapped/written by the
    // nopCommerce LinqToDB stack, so writing the enum directly left the column stuck at 0.
    // StatusId is the real mapped column; the Status wrapper below is the typed API.
    [Column("Status")]
    [ToonDescription(Purpose = "Item lifecycle status, stored as int. See the Status wrapper for the enum semantics.")]
    public int StatusId { get; set; }

    [NotColumn, System.ComponentModel.DataAnnotations.Schema.NotMapped]
    [ToonDescription(Purpose = "Item lifecycle: Pending / Fulfilled (fully allocated) / PartiallyFulfilled (partly allocated) / Dropped (expired or no incoming stock).",
        BusinessRule = "set during conversion: FulfilledQuantity >= RequestedQuantity ? Fulfilled : FulfilledQuantity > 0 ? PartiallyFulfilled : Dropped; stays Pending until first allocation. Persisted via StatusId.")]
    public PreOrderItemStatus Status
    {
        get => (PreOrderItemStatus)StatusId;
        set => StatusId = (int)value;
    }
}
