using System.ComponentModel.DataAnnotations;
using PowderCoating.Core.Enums;

namespace PowderCoating.Application.DTOs.PurchaseOrder;

// ============================================================================
// LIST / SUMMARY
// ============================================================================

public class PurchaseOrderListDto
{
    public int Id { get; set; }
    public string PoNumber { get; set; } = string.Empty;
    public int VendorId { get; set; }
    public string VendorName { get; set; } = string.Empty;
    public PurchaseOrderStatus Status { get; set; }
    public DateTime OrderDate { get; set; }
    public DateTime? ExpectedDeliveryDate { get; set; }
    public DateTime? ReceivedDate { get; set; }
    public decimal ShippingCost { get; set; }
    public decimal SubTotal { get; set; }
    public decimal TotalAmount { get; set; }
    public int ItemCount { get; set; }

    public bool IsOverdue =>
        Status is PurchaseOrderStatus.Draft or PurchaseOrderStatus.Submitted or PurchaseOrderStatus.PartiallyReceived
        && ExpectedDeliveryDate.HasValue
        && ExpectedDeliveryDate.Value.Date < DateTime.UtcNow.Date;
}

// ============================================================================
// DETAILS
// ============================================================================

public class PurchaseOrderDto
{
    public int Id { get; set; }
    public string PoNumber { get; set; } = string.Empty;
    public int VendorId { get; set; }
    public string VendorName { get; set; } = string.Empty;
    public string? VendorEmail { get; set; }
    public string? VendorPhone { get; set; }
    public PurchaseOrderStatus Status { get; set; }
    public DateTime OrderDate { get; set; }
    public DateTime? ExpectedDeliveryDate { get; set; }
    public DateTime? ReceivedDate { get; set; }
    public decimal ShippingCost { get; set; }
    public decimal SubTotal { get; set; }
    public decimal TotalAmount { get; set; }
    public string? Notes { get; set; }
    public string? InternalNotes { get; set; }
    public int? BillId { get; set; }
    public string? BillNumber { get; set; }
    public List<PurchaseOrderItemDto> Items { get; set; } = new();

    public bool IsOverdue =>
        Status is PurchaseOrderStatus.Draft or PurchaseOrderStatus.Submitted or PurchaseOrderStatus.PartiallyReceived
        && ExpectedDeliveryDate.HasValue
        && ExpectedDeliveryDate.Value.Date < DateTime.UtcNow.Date;
}

// ============================================================================
// CREATE / UPDATE
// ============================================================================

public class CreatePurchaseOrderDto
{
    [Required]
    public int VendorId { get; set; }

    [Required]
    [Display(Name = "Order Date")]
    public DateTime OrderDate { get; set; } = DateTime.Today;

    [Display(Name = "Expected Delivery")]
    public DateTime? ExpectedDeliveryDate { get; set; }

    [Display(Name = "Shipping Cost")]
    [Range(0, 999999)]
    public decimal ShippingCost { get; set; } = 0;

    [Display(Name = "Notes")]
    [StringLength(1000)]
    public string? Notes { get; set; }

    [Display(Name = "Internal Notes")]
    [StringLength(1000)]
    public string? InternalNotes { get; set; }

    public List<CreatePurchaseOrderItemDto> Items { get; set; } = new();
}

public class UpdatePurchaseOrderDto
{
    [Required]
    public int VendorId { get; set; }

    [Required]
    [Display(Name = "Order Date")]
    public DateTime OrderDate { get; set; } = DateTime.Today;

    [Display(Name = "Expected Delivery")]
    public DateTime? ExpectedDeliveryDate { get; set; }

    [Display(Name = "Shipping Cost")]
    [Range(0, 999999)]
    public decimal ShippingCost { get; set; } = 0;

    [Display(Name = "Notes")]
    [StringLength(1000)]
    public string? Notes { get; set; }

    [Display(Name = "Internal Notes")]
    [StringLength(1000)]
    public string? InternalNotes { get; set; }

    public List<CreatePurchaseOrderItemDto> Items { get; set; } = new();
}

// ============================================================================
// LINE ITEMS
// ============================================================================

public class PurchaseOrderItemDto
{
    public int Id { get; set; }
    public int PurchaseOrderId { get; set; }
    public int? InventoryItemId { get; set; }
    public string ItemName { get; set; } = string.Empty;   // Inventory item name OR custom description
    public string ItemSKU { get; set; } = string.Empty;
    public string UnitOfMeasure { get; set; } = string.Empty;
    public bool IsCustomItem => InventoryItemId == null;
    public decimal QuantityOrdered { get; set; }
    public decimal QuantityReceived { get; set; }
    public decimal UnitCost { get; set; }
    public decimal LineTotal { get; set; }
    public string? Notes { get; set; }

    public bool IsFullyReceived => QuantityReceived >= QuantityOrdered;
    public decimal QuantityRemaining => Math.Max(0, QuantityOrdered - QuantityReceived);
}

public class CreatePurchaseOrderItemDto
{
    // Null = custom/non-inventory line item
    public int? InventoryItemId { get; set; }

    // Required when InventoryItemId is null
    [StringLength(200)]
    public string? Description { get; set; }

    [StringLength(50)]
    public string? UnitOfMeasure { get; set; }

    [Required]
    [Range(0.001, 999999, ErrorMessage = "Quantity must be greater than 0")]
    public decimal QuantityOrdered { get; set; }

    [Required]
    [Range(0, 999999)]
    public decimal UnitCost { get; set; }

    [StringLength(500)]
    public string? Notes { get; set; }
}

// ============================================================================
// RECEIVING
// ============================================================================

public class ReceivePurchaseOrderDto
{
    [Required]
    [Display(Name = "Received Date")]
    public DateTime ReceivedDate { get; set; } = DateTime.Today;

    [StringLength(500)]
    public string? Notes { get; set; }

    public List<ReceiveItemDto> Items { get; set; } = new();
}

public class ReceiveItemDto
{
    public int PurchaseOrderItemId { get; set; }
    public int? InventoryItemId { get; set; }
    public string ItemName { get; set; } = string.Empty;
    public string ItemSKU { get; set; } = string.Empty;
    public string UnitOfMeasure { get; set; } = string.Empty;
    public decimal QuantityOrdered { get; set; }
    public decimal QuantityAlreadyReceived { get; set; }
    public decimal QuantityRemaining { get; set; }

    [Range(0, 999999)]
    public decimal QuantityToReceive { get; set; }
}
