using Books.Api.Domain.Orders;
using EventFlow.Commands;

namespace Books.Api.Commands.Orders;

/// <summary>
/// Creates a new order draft for a customer.
/// </summary>
public class CreateOrderCommand(
    OrderId orderId,
    string companyId,
    string fiscalYearId,
    string customerId,
    string customerName,
    string customerNumber,
    string orderNumber,
    DateOnly orderDate,
    DateOnly? expectedDeliveryDate,
    string currency,
    string? vatCode,
    string? notes,
    string? reference,
    string createdBy) : Command<OrderAggregate, OrderId>(orderId)
{
    public string CompanyId { get; } = companyId;
    public string FiscalYearId { get; } = fiscalYearId;
    public string CustomerId { get; } = customerId;
    public string CustomerName { get; } = customerName;
    public string CustomerNumber { get; } = customerNumber;
    public string OrderNumber { get; } = orderNumber;
    public DateOnly OrderDate { get; } = orderDate;
    public DateOnly? ExpectedDeliveryDate { get; } = expectedDeliveryDate;
    public string Currency { get; } = currency;
    public string? VatCode { get; } = vatCode;
    public string? Notes { get; } = notes;
    public string? Reference { get; } = reference;
    public string CreatedBy { get; } = createdBy;
}

/// <summary>
/// Adds a line to an order draft.
/// </summary>
public class AddOrderLineCommand(
    OrderId orderId,
    string description,
    decimal quantity,
    decimal unitPrice,
    string vatCode,
    string? accountId = null,
    string? unit = null,
    decimal discountPercent = 0,
    string? productId = null) : Command<OrderAggregate, OrderId>(orderId)
{
    public string Description { get; } = description;
    public decimal Quantity { get; } = quantity;
    public decimal UnitPrice { get; } = unitPrice;
    public string VatCode { get; } = vatCode;
    public string? AccountId { get; } = accountId;
    public string? Unit { get; } = unit;
    public decimal DiscountPercent { get; } = discountPercent;
    public string? ProductId { get; } = productId;
}

/// <summary>
/// Updates a line on an order draft.
/// </summary>
public class UpdateOrderLineCommand(
    OrderId orderId,
    int lineNumber,
    string description,
    decimal quantity,
    decimal unitPrice,
    string vatCode,
    string? accountId = null,
    string? unit = null,
    decimal discountPercent = 0,
    string? productId = null) : Command<OrderAggregate, OrderId>(orderId)
{
    public int LineNumber { get; } = lineNumber;
    public string Description { get; } = description;
    public decimal Quantity { get; } = quantity;
    public decimal UnitPrice { get; } = unitPrice;
    public string VatCode { get; } = vatCode;
    public string? AccountId { get; } = accountId;
    public string? Unit { get; } = unit;
    public decimal DiscountPercent { get; } = discountPercent;
    public string? ProductId { get; } = productId;
}

/// <summary>
/// Removes a line from an order draft.
/// </summary>
public class RemoveOrderLineCommand(
    OrderId orderId,
    int lineNumber) : Command<OrderAggregate, OrderId>(orderId)
{
    public int LineNumber { get; } = lineNumber;
}

/// <summary>
/// Confirms an order.
/// </summary>
public class ConfirmOrderCommand(
    OrderId orderId,
    string confirmedBy) : Command<OrderAggregate, OrderId>(orderId)
{
    public string ConfirmedBy { get; } = confirmedBy;
}

/// <summary>
/// Marks specified lines on an order as invoiced.
/// </summary>
public class MarkOrderLinesInvoicedCommand(
    OrderId orderId,
    string invoiceId,
    string invoiceNumber,
    IReadOnlyList<int> lineNumbers,
    string invoicedBy) : Command<OrderAggregate, OrderId>(orderId)
{
    public string InvoiceId { get; } = invoiceId;
    public string InvoiceNumber { get; } = invoiceNumber;
    public IReadOnlyList<int> LineNumbers { get; } = lineNumbers;
    public string InvoicedBy { get; } = invoicedBy;
}

/// <summary>
/// Cancels an order.
/// </summary>
public class CancelOrderCommand(
    OrderId orderId,
    string reason,
    string cancelledBy) : Command<OrderAggregate, OrderId>(orderId)
{
    public string Reason { get; } = reason;
    public string CancelledBy { get; } = cancelledBy;
}
