#nullable enable
using Baya.Application.Models.Invoices;
using Baya.Domain.Entities.Invoices;

namespace Baya.Application.Contracts.Persistence;

/// <summary>
/// The invoices aggregate. One issued invoice per booking (idempotent). The sequential <c>invoice_number</c> is
/// drawn from a concurrency-safe counter row via <see cref="ReserveNextInvoiceNumberAsync"/>, whose increment
/// commits in the same transaction as the invoice insert. Money is IRR <c>long</c>.
/// </summary>
public interface IInvoiceRepository
{
    /// <summary>The booking facts the invoice copies + the owning customer's user id (tenancy). Null when the
    /// booking is absent.</summary>
    Task<InvoiceBookingAmounts?> GetBookingAmountsAsync(long bookingId, CancellationToken cancellationToken);

    /// <summary>The existing issued invoice for a booking, if any — the idempotency check (re-issue returns it).</summary>
    Task<Invoice?> GetTrackedByBookingIdAsync(long bookingId, CancellationToken cancellationToken);

    /// <summary>The booking's invoice projected for the read, with the owning customer's user id for tenancy.
    /// Null when none is issued yet.</summary>
    Task<InvoiceProjection?> GetByBookingIdAsync(long bookingId, CancellationToken cancellationToken);

    /// <summary>Tracked invoices still walking the مودیان state (<c>pending</c>/<c>submitted</c>), oldest first,
    /// capped at <paramref name="max"/> — the refinement-phase-8 reconciliation poll re-submits each until مودیان
    /// returns the 22-digit reference (or rejects it).</summary>
    Task<IReadOnlyList<Invoice>> GetUnregisteredMoadianInvoicesAsync(int max, CancellationToken cancellationToken);

    Task AddInvoiceAsync(Invoice invoice, CancellationToken cancellationToken);

    /// <summary>Reads and increments the tracked counter row and returns the reserved value. The increment is
    /// <b>not</b> committed here — the caller commits it alongside the invoice insert so numbers stay gap-free
    /// under a rollback. Call under the invoice-number lock.</summary>
    Task<long> ReserveNextInvoiceNumberAsync(CancellationToken cancellationToken);
}
