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

namespace Books.Api.Commands.Invoices;

/// <summary>
/// Creates a new credit note draft for a customer.
/// Credit note number is assigned at creation (Momsloven §52).
/// </summary>
public class CreateCreditNoteCommand(
    InvoiceId invoiceId,
    string companyId,
    string fiscalYearId,
    string customerId,
    string customerName,
    string customerNumber,
    string creditNoteNumber,
    DateOnly creditNoteDate,
    string currency,
    string? vatCode,
    string? notes,
    string? reference,
    string createdBy,
    string? originalInvoiceId = null,
    string? originalInvoiceNumber = null,
    string? creditReason = null) : Command<InvoiceAggregate, InvoiceId>(invoiceId)
{
    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 CreditNoteNumber { get; } = creditNoteNumber;
    public DateOnly CreditNoteDate { get; } = creditNoteDate;
    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;
    public string? OriginalInvoiceId { get; } = originalInvoiceId;
    public string? OriginalInvoiceNumber { get; } = originalInvoiceNumber;
    public string? CreditReason { get; } = creditReason;
}

/// <summary>
/// Issues a credit note (posts to ledger).
/// This is the credit note equivalent of MarkInvoiceSentCommand.
/// Should be called after successfully posting to the ledger.
/// </summary>
public class IssueCreditNoteCommand(
    InvoiceId invoiceId,
    string ledgerTransactionId,
    string issuedBy) : Command<InvoiceAggregate, InvoiceId>(invoiceId)
{
    public string LedgerTransactionId { get; } = ledgerTransactionId;
    public string IssuedBy { get; } = issuedBy;
}

/// <summary>
/// Applies a credit note to an invoice, reducing the invoice's outstanding balance.
/// </summary>
public class ApplyCreditNoteCommand(
    InvoiceId creditNoteId,
    string targetInvoiceId,
    string targetInvoiceNumber,
    decimal amount,
    DateOnly appliedDate,
    string appliedBy,
    string? ledgerTransactionId = null) : Command<InvoiceAggregate, InvoiceId>(creditNoteId)
{
    public string TargetInvoiceId { get; } = targetInvoiceId;
    public string TargetInvoiceNumber { get; } = targetInvoiceNumber;
    public decimal Amount { get; } = amount;
    public DateOnly AppliedDate { get; } = appliedDate;
    public string AppliedBy { get; } = appliedBy;
    public string? LedgerTransactionId { get; } = ledgerTransactionId;
}
