#nullable enable
using Baya.Application.Models.Common;
using Baya.Application.Models.Refunds;
using Baya.Domain.Entities.Refunds;

namespace Baya.Application.Contracts.Persistence;

/// <summary>
/// The refunds/clawbacks aggregate. Writes load tracked rows; reads project to DTOs. The ledger legs
/// themselves are appended through <see cref="IPaymentRepository.AddLedgerEntriesAsync"/> (b10's helper) — this
/// repo owns only the refund/clawback rows and the money facts a refund is validated against. Money is IRR
/// <c>long</c>; the <c>Σ refunded ≤ captured</c> invariant is enforced in the handler from
/// <see cref="GetRefundedSumForTransactionAsync"/> under the booking refund lock.
/// </summary>
public interface IRefundRepository
{
    /// <summary>The booking's frozen money split + b9 cancellation snapshot + its captured (succeeded)
    /// transaction — everything a refund is decomposed and channel-picked from. Null when the booking has no
    /// captured payment (refund is impossible).</summary>
    Task<RefundMoneyContext?> GetRefundContextAsync(long bookingId, CancellationToken cancellationToken);

    /// <summary>The sum of prior non-failed/-rejected refund <c>amount</c> for a transaction — the authoritative
    /// backstop for <c>Σ refunded ≤ captured</c> (this refund's amount is added on top in the handler).</summary>
    Task<long> GetRefundedSumForTransactionAsync(long paymentTransactionId, CancellationToken cancellationToken);

    Task AddRefundAsync(Refund refund, CancellationToken cancellationToken);
    Task AddClawbackAsync(NurseClawback clawback, CancellationToken cancellationToken);

    /// <summary>Tracked pending clawback — for the admin write-off. Null when absent or already resolved.</summary>
    Task<NurseClawback?> GetTrackedClawbackByIdAsync(long id, CancellationToken cancellationToken);

    /// <summary>Tracked refund row — for the settlement confirm/fail transition of a <c>processing</c> refund.
    /// Null when absent.</summary>
    Task<Refund?> GetTrackedRefundByIdAsync(long id, CancellationToken cancellationToken);

    /// <summary>The id of the <c>processing</c> refund for a captured transaction — the BNPL cash-back callback
    /// resolves the refund it should settle from the same <c>payment_transaction</c> the revert was created
    /// against. Null when there is no in-flight (processing) refund for it.</summary>
    Task<long?> GetProcessingRefundIdForTransactionAsync(long paymentTransactionId, CancellationToken cancellationToken);

    Task<PagedResult<RefundListItemDto>> ListAsync(long? bookingId, string? status, int page, int pageSize, CancellationToken cancellationToken);

    /// <summary>The customer-facing status of a single refund, with the owning customer's user id for tenancy.
    /// Null when absent.</summary>
    Task<RefundStatusProjection?> GetStatusAsync(long id, CancellationToken cancellationToken);

    /// <summary>The customer-facing status of a booking's (latest) refund, with the owning customer's user id
    /// for tenancy. Null when the booking has no refund. Lets the customer reach a refund from its booking.</summary>
    Task<RefundStatusProjection?> GetStatusByBookingAsync(long bookingId, CancellationToken cancellationToken);

    /// <summary>The provider revert reference on a <c>bnpl_revert</c> refund — the BNPL revert path records it
    /// as <c>revert_transaction_id</c> on the <c>bnpl_transactions</c> row. Null when absent.</summary>
    Task<string?> GetExternalRevertReferenceAsync(long refundId, CancellationToken cancellationToken);
}
