using System.ComponentModel.DataAnnotations;
using ERPCore.Domain.Enums;

namespace ERPCore.Dtos.Sales;

public sealed record SalesSlipLineDto(
    int SalesSlipLineId, int ItemId, string Description, decimal Qty, decimal FreeQty,
    int WarehouseId, decimal UnitPrice, decimal BaseCost, string PriceSource, decimal DiscountPct,
    decimal DiscountAmount, SalesDiscountMode DiscountMode, decimal NetUnitPrice, decimal LineTotal,
    decimal TaxPct, decimal TaxAmount, bool IsFreeIssue, int? ParentLineId);

public sealed record SalesSlipTotalsDto(
    decimal Subtotal, decimal DiscountTotal, decimal FreeQtyTotal, decimal TaxTotal, decimal GrandTotal,
    decimal PaidAmount, decimal BalanceAmount);

public sealed record SalesSlipDto(
    int SalesSlipId, string SlipNo, DateTime SlipDate, int CustomerId,
    string CustomerSnapshotName, int WarehouseId, int CashierUserId, SalesSlipStatus Status,
    DateTime CreatedAt, DateTime? UpdatedAt, SalesSlipTotalsDto Totals, IReadOnlyList<SalesSlipLineDto> Lines);

public sealed record SalesSlipSummaryDto(
    int SalesSlipId, string SlipNo, DateTime SlipDate, int CustomerId,
    string CustomerSnapshotName, int WarehouseId, SalesSlipStatus Status,
    SalesSlipTotalsDto Totals, DateTime CreatedAt);

public sealed record SalesSlipPostingIssueDto(
    int SalesSlipLineId, int ItemId, string ItemSku, string ItemName, int WarehouseId,
    decimal RequestedQty, decimal AvailableQty, decimal ShortQty, bool IsFreeIssue);

public sealed record SalesSlipPostingCheckDto(
    int SalesSlipId, string SlipNo, SalesSlipStatus Status, bool CanPost,
    IReadOnlyList<SalesSlipPostingIssueDto> Issues);

public sealed record FreeIssueSummaryDto(
    int SalesSlipId, string SlipNo, SalesSlipStatus Status, DateTime CreatedAt,
    int WarehouseId, string WarehouseName, int ItemId, string ItemSku, string ItemName,
    string UomName, decimal Qty, decimal FreeQty, string SchemeLabel);

public sealed record FreeIssueDto(
    int SalesSlipId, string SlipNo, DateTime SlipDate, SalesSlipStatus Status,
    int CustomerId, string CustomerSnapshotName, int WarehouseId, string WarehouseName,
    int CashierUserId, DateTime CreatedAt, DateTime? UpdatedAt, FreeIssueSummaryDto Summary,
    IReadOnlyList<SalesSlipLineDto> Lines);

public sealed class CreateSalesSlipLineRequest
{
    [Required] public int ItemId { get; set; }
    [Required] public int WarehouseId { get; set; }
    [Range(0.0001, double.MaxValue)] public decimal Qty { get; set; }
    [Range(0, double.MaxValue)] public decimal FreeQty { get; set; }
    [Range(0, double.MaxValue)] public decimal? UnitPrice { get; set; }
    public bool AllowManualPriceOverride { get; set; }
    [Required, EnumDataType(typeof(SalesDiscountMode))] public SalesDiscountMode DiscountMode { get; set; } = SalesDiscountMode.Percentage;
    [Range(0, 100)] public decimal DiscountPct { get; set; }
    [Range(0, double.MaxValue)] public decimal DiscountAmount { get; set; }
    [Range(0, double.MaxValue)] public decimal DiscountValue { get; set; }
    [Range(0, 100)] public decimal TaxPct { get; set; }
    public bool IsFreeIssue { get; set; }
    public int? ParentLineId { get; set; }
}

public sealed class CreateSalesSlipRequest
{
    [Required] public int CustomerId { get; set; }
    [Required] public int WarehouseId { get; set; }
    [Required] public int CashierUserId { get; set; }
    [Required, MinLength(1)] public List<CreateSalesSlipLineRequest> Lines { get; set; } = new();
}

public sealed class UpdateSalesSlipRequest
{
    [Required] public int CustomerId { get; set; }
    [Required] public int WarehouseId { get; set; }
    [Required] public int CashierUserId { get; set; }
    [Required, MinLength(1)] public List<CreateSalesSlipLineRequest> Lines { get; set; } = new();
}
