using Baya.Domain.Entities.Bnpl;
using Baya.Domain.Entities.Payments;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace Baya.Infrastructure.Persistence.Configuration.BnplConfig;

/// <summary>
/// <c>bnpl_transactions</c> — one row per BNPL order, <b>1:1 with its <c>payment_transaction</c></b>. The
/// <c>UNIQUE(payment_transaction_id)</c> is the structural one-BNPL-row-per-order guard; the settle invariant
/// <c>settled = order − commission</c> (with both net + commission set together) is a DB CHECK mirroring b9/b11.
/// The state-machine guard on <c>status</c> lives in the entity; there is no <c>bnpl_settlement_entries</c> child
/// table (tranched settlement is DEFERRED — adding it later is a purely additive migration).
/// </summary>
internal sealed class BnplTransactionConfig : IEntityTypeConfiguration<BnplTransaction>
{
    public void Configure(EntityTypeBuilder<BnplTransaction> builder)
    {
        builder.ToTable("BnplTransactions", "payments", t => t.HasCheckConstraint(
            "CK_BnplTransactions_SettleSplit",
            "([SettledAmountIrr] IS NULL AND [BnplCommissionIrr] IS NULL) " +
            "OR ([SettledAmountIrr] = [OrderAmountIrr] - [BnplCommissionIrr] " +
            "AND [SettledAmountIrr] >= 0 AND [BnplCommissionIrr] >= 0)"));

        builder.Property(t => t.ProviderCode).HasMaxLength(50).IsRequired();
        builder.Property(t => t.MerchantOfRecord).HasMaxLength(40).IsRequired();
        builder.Property(t => t.ExternalPaymentToken).HasMaxLength(200);
        builder.Property(t => t.ExternalTransactionId).HasMaxLength(200);
        builder.Property(t => t.EligibilityStatus).HasMaxLength(30);
        builder.Property(t => t.Currency).HasMaxLength(5).IsRequired();
        builder.Property(t => t.Status).HasMaxLength(30).IsRequired();
        builder.Property(t => t.RevertTransactionId).HasMaxLength(200);
        builder.Property(t => t.RefundChannel).HasMaxLength(20);

        // Strict 1:1 — exactly one BNPL row per order. The structural guard, not just a handler pre-check.
        builder.HasIndex(t => t.PaymentTransactionId).IsUnique();
        // The callback dispatch resolves the order from the provider token in the payload.
        builder.HasIndex(t => t.ExternalPaymentToken).HasFilter("[ExternalPaymentToken] IS NOT NULL");
        builder.HasIndex(t => t.Status);

        builder.HasOne<PaymentTransaction>().WithMany().HasForeignKey(t => t.PaymentTransactionId).IsRequired();

        builder.HasQueryFilter(t => t.DeletedAt == null);
    }
}
