#nullable enable
using Baya.Domain.Common;

namespace Baya.Domain.Entities.Refunds;

/// <summary>
/// A first-class receivable opened when a booking is refunded/disputed <b>after</b> the nurse was already paid.
/// Because an Iranian IBAN transfer is effectively irreversible, that money is already gone and must be
/// recorded as owed-back — never silently absorbed. The receivable's ledger leg is
/// <c>DEBIT nurse_clawback_receivable</c>; the balance derives from the ledger, this row tracks the workflow.
/// <para>
/// This phase only ever creates rows in <see cref="ClawbackStatus.Pending"/> and supports an admin write-off.
/// <see cref="RecoveredInPayoutId"/> / <see cref="OriginalPayoutId"/> are the (nullable) join points b13 fills
/// when a payout batch nets the clawback out — <c>nurse_payouts</c> arrives in b13.
/// </para>
/// </summary>
public class NurseClawback : BaseEntity<long>, IAuditable
{
    public long NurseId { get; set; }
    public long BookingId { get; set; }
    public long RefundId { get; set; }

    /// <summary>The payout that already paid the nurse. FK target (<c>nurse_payouts</c>) arrives in b13; the
    /// column/index are in place now and the value is set once b13 exists.</summary>
    public long? OriginalPayoutId { get; set; }

    /// <summary>Equals the refund's <c>nurse_payout_refunded_irr</c> leg (IRR).</summary>
    public long AmountIrr { get; set; }

    public string Status { get; private set; } = ClawbackStatus.Pending;

    /// <summary>The batch that netted it out. Set by <b>b13</b> only — always null here.</summary>
    public long? RecoveredInPayoutId { get; set; }

    public DateTime? ResolvedAt { get; private set; }
    public string? ResolutionNotes { get; private set; }

    public DateTimeOffset? DeletedAt { get; set; }

    public bool IsPending => Status == ClawbackStatus.Pending;

    /// <summary>Netted out of a payout batch (b13): records the recovering payout + resolution. The balancing
    /// <c>DEBIT nurse_payable / CREDIT nurse_clawback_receivable</c> posting is the payout handler's job; this
    /// records the workflow outcome. Only a <c>pending</c> clawback can be recovered.</summary>
    public void Recover(long payoutId, DateTime now)
    {
        if (Status != ClawbackStatus.Pending)
            throw new InvalidOperationException($"Only a pending clawback can be recovered (was {Status}).");
        Status = ClawbackStatus.Recovered;
        RecoveredInPayoutId = payoutId;
        ResolvedAt = now;
    }

    /// <summary>Admin declares the receivable uncollectable. The balancing <c>bad_debt</c> posting is the
    /// handler's job; this records the workflow outcome.</summary>
    public void WriteOff(string notes, DateTime now)
    {
        if (Status != ClawbackStatus.Pending)
            throw new InvalidOperationException($"Only a pending clawback can be written off (was {Status}).");
        Status = ClawbackStatus.WrittenOff;
        ResolutionNotes = notes;
        ResolvedAt = now;
    }
}
