using Baya.Domain.Entities.Payments;

namespace Baya.Test.Foundation.Payments;

public class LedgerPostingTests
{
    private static readonly DateTime Now = new(2026, 7, 6, 10, 0, 0, DateTimeKind.Utc);

    [Fact]
    public void CardCapture_posts_three_legs_that_balance()
    {
        var legs = LedgerPosting.CardCapture(
            bookingId: 42, nurseId: 7, grossIrr: 23_300_000, commissionIrr: 3_495_000, payoutIrr: 19_805_000,
            paymentTransactionId: 100, createdAt: Now);

        Assert.Equal(3, legs.Count);

        var debits = legs.Where(l => l.Direction == LedgerDirection.Debit).Sum(l => l.AmountIrr);
        var credits = legs.Where(l => l.Direction == LedgerDirection.Credit).Sum(l => l.AmountIrr);
        Assert.Equal(debits, credits);
        Assert.Equal(23_300_000, debits);

        var escrow = legs.Single(l => l.AccountType == LedgerAccountType.EscrowHeld);
        Assert.Equal(LedgerDirection.Debit, escrow.Direction);
        Assert.Equal(23_300_000, escrow.AmountIrr);

        var revenue = legs.Single(l => l.AccountType == LedgerAccountType.PlatformRevenue);
        Assert.Equal(LedgerDirection.Credit, revenue.Direction);
        Assert.Equal(3_495_000, revenue.AmountIrr);

        var payable = legs.Single(l => l.AccountType == LedgerAccountType.NursePayable);
        Assert.Equal(LedgerDirection.Credit, payable.Direction);
        Assert.Equal(19_805_000, payable.AmountIrr);
        Assert.Equal(7, payable.NurseId);

        // One shared group; amounts positive; sign carried by direction.
        Assert.Single(legs.Select(l => l.TransactionGroupId).Distinct());
        Assert.All(legs, l => Assert.True(l.AmountIrr > 0));
    }

    [Fact]
    public void CardCapture_throws_when_amounts_do_not_reconcile()
    {
        Assert.Throws<InvalidOperationException>(() => LedgerPosting.CardCapture(
            bookingId: 1, nurseId: 1, grossIrr: 100, commissionIrr: 10, payoutIrr: 80, // 10 + 80 != 100
            paymentTransactionId: 1, createdAt: Now));
    }
}
