namespace Books.Api.Domain.Orders;

/// <summary>
/// Order status representing the lifecycle of an order.
/// Workflow: Draft -> Confirmed -> PartiallyInvoiced/FullyInvoiced (or Cancelled at any point before FullyInvoiced)
/// </summary>
public enum OrderStatus
{
    /// <summary>
    /// Order is being prepared, not yet confirmed.
    /// Lines can be added, updated, or removed.
    /// </summary>
    Draft,

    /// <summary>
    /// Order has been confirmed and is ready for fulfillment/invoicing.
    /// Lines can no longer be modified.
    /// </summary>
    Confirmed,

    /// <summary>
    /// Some but not all lines have been invoiced.
    /// </summary>
    PartiallyInvoiced,

    /// <summary>
    /// All lines have been invoiced.
    /// Order is complete.
    /// </summary>
    FullyInvoiced,

    /// <summary>
    /// Order has been cancelled.
    /// Can only cancel Draft or Confirmed orders (not after invoicing has started).
    /// </summary>
    Cancelled
}

public static class OrderStatusExtensions
{
    public static string ToStringValue(this OrderStatus status) => status switch
    {
        OrderStatus.Draft => "draft",
        OrderStatus.Confirmed => "confirmed",
        OrderStatus.PartiallyInvoiced => "partially_invoiced",
        OrderStatus.FullyInvoiced => "fully_invoiced",
        OrderStatus.Cancelled => "cancelled",
        _ => throw new ArgumentOutOfRangeException(nameof(status))
    };

    public static OrderStatus FromString(string value) => value.ToLowerInvariant() switch
    {
        "draft" => OrderStatus.Draft,
        "confirmed" => OrderStatus.Confirmed,
        "partially_invoiced" => OrderStatus.PartiallyInvoiced,
        "fully_invoiced" => OrderStatus.FullyInvoiced,
        "cancelled" => OrderStatus.Cancelled,
        _ => throw new ArgumentException($"Unknown order status: {value}", nameof(value))
    };

    /// <summary>
    /// Returns true if the order can be modified (lines added/removed).
    /// Only drafts can be modified.
    /// </summary>
    public static bool CanModify(this OrderStatus status) => status == OrderStatus.Draft;

    /// <summary>
    /// Returns true if the order can be confirmed.
    /// Only drafts with at least one line can be confirmed.
    /// </summary>
    public static bool CanConfirm(this OrderStatus status) => status == OrderStatus.Draft;

    /// <summary>
    /// Returns true if lines from this order can be invoiced.
    /// Confirmed and PartiallyInvoiced orders can have lines invoiced.
    /// </summary>
    public static bool CanInvoice(this OrderStatus status) =>
        status == OrderStatus.Confirmed || status == OrderStatus.PartiallyInvoiced;

    /// <summary>
    /// Returns true if the order can be cancelled.
    /// Cannot cancel after any lines have been invoiced.
    /// </summary>
    public static bool CanCancel(this OrderStatus status) =>
        status == OrderStatus.Draft || status == OrderStatus.Confirmed;
}
