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

namespace ERPCore.Dtos.Sales;

public sealed record SalesInvoiceLineDto(
    int SalesInvoiceLineId, 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 SalesInvoiceTotalsDto(
    decimal Subtotal, decimal DiscountTotal, decimal FreeQtyTotal, decimal TaxTotal, decimal GrandTotal,
    decimal RoundOff, decimal NetPayable, decimal PaidAmount, decimal BalanceAmount);

public sealed record SalesInvoiceDto(
    int SalesInvoiceId, string InvoiceNo, DateTime InvoiceDate, int CustomerId,
    string CustomerSnapshotName, string? CustomerSnapshotTaxNo, int WarehouseId,
    SalesInvoiceType InvoiceType, SalesInvoiceStatus Status, int CreatedBy, DateTime CreatedAt,
    DateTime? UpdatedAt, string? GlJournalNo, DateTime? GlPostedAt,
    SalesInvoiceTotalsDto Totals, IReadOnlyList<SalesInvoiceLineDto> Lines);

public sealed record SalesInvoiceSummaryDto(
    int SalesInvoiceId, string InvoiceNo, DateTime InvoiceDate, int CustomerId,
    string CustomerSnapshotName, int WarehouseId, SalesInvoiceType InvoiceType,
    SalesInvoiceStatus Status, SalesInvoiceTotalsDto Totals, DateTime CreatedAt, string? GlJournalNo);

public sealed record SalesInvoicePaymentDto(
    int SalesInvoicePaymentId, int SalesInvoiceId, decimal Amount, DateTime PaymentDate,
    long GlBankAccountId, string BankAccountName, string? Reference, string? GlJournalNo, DateTime CreatedAt);

public sealed class CreateSalesInvoicePaymentRequest
{
    [Range(0.01, double.MaxValue)] public decimal Amount { get; set; }
    [Required] public long GlBankAccountId { get; set; }
    [StringLength(100)] public string? Reference { get; set; }
}

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

public sealed record SalesInvoicePostingCheckDto(
    int SalesInvoiceId, string InvoiceNo, SalesInvoiceStatus Status, bool CanPost,
    IReadOnlyList<SalesInvoicePostingIssueDto> Issues);

public sealed class CreateSalesInvoiceLineRequest
{
    [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 CreateSalesInvoiceRequest
{
    [Required] public int CustomerId { get; set; }
    [Required] public int WarehouseId { get; set; }
    [Required, EnumDataType(typeof(SalesInvoiceType))] public SalesInvoiceType InvoiceType { get; set; } = SalesInvoiceType.B2C;
    [Required, MinLength(1)] public List<CreateSalesInvoiceLineRequest> Lines { get; set; } = new();
}

public sealed class UpdateSalesInvoiceRequest
{
    [Required] public int CustomerId { get; set; }
    [Required] public int WarehouseId { get; set; }
    [Required, EnumDataType(typeof(SalesInvoiceType))] public SalesInvoiceType InvoiceType { get; set; } = SalesInvoiceType.B2C;
    [Required, MinLength(1)] public List<CreateSalesInvoiceLineRequest> Lines { get; set; } = new();
}
