using Baya.Domain.Entities.Booking;
using Baya.Domain.Entities.Identity;
using Baya.Domain.Entities.Messaging;
using Baya.Domain.Entities.Payments;
using Baya.Domain.Entities.Refunds;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace Baya.Infrastructure.Persistence.Configuration.RefundsConfig;

/// <summary>
/// <c>refunds</c> — 1:N per <c>payment_transaction</c>. The <c>amount = fee_leg + payout_leg</c> reconciliation
/// is a DB CHECK (the "Σ refunded ≤ captured" invariant is a handler check under the booking refund lock, not a
/// single-row constraint). <c>ticket_id</c> is a nullable FK to <c>messaging.Tickets</c> (b15 shipped the table;
/// refinement-phase-6 added the constraint, <c>ON DELETE NO ACTION</c>).
/// </summary>
internal sealed class RefundConfig : IEntityTypeConfiguration<Refund>
{
    public void Configure(EntityTypeBuilder<Refund> builder)
    {
        builder.ToTable("Refunds", "payments", t => t.HasCheckConstraint(
            "CK_Refunds_LegSplit",
            "[Amount] = [PlatformFeeRefundedIrr] + [NursePayoutRefundedIrr] " +
            "AND [Amount] >= 0 AND [PlatformFeeRefundedIrr] >= 0 AND [NursePayoutRefundedIrr] >= 0"));

        builder.Property(r => r.RefundChannel).HasMaxLength(20).IsRequired();
        builder.Property(r => r.Status).HasMaxLength(20).IsRequired();
        builder.Property(r => r.ReasonCategory).HasMaxLength(50);
        builder.Property(r => r.ReasonNotes).HasMaxLength(1000);
        builder.Property(r => r.AdminNotes).HasMaxLength(1000);
        builder.Property(r => r.RejectedReason).HasMaxLength(500);
        builder.Property(r => r.GatewayRefundReference).HasMaxLength(200);
        builder.Property(r => r.ExternalRevertReference).HasMaxLength(200);
        builder.Property(r => r.CancellationPolicyCode).HasMaxLength(50);
        builder.Property(r => r.RefundPercentage).HasPrecision(6, 4);
        builder.Property(r => r.RefundPercentageApplied).HasPrecision(5, 2);

        builder.HasIndex(r => r.PaymentTransactionId);
        builder.HasIndex(r => r.BookingId);
        builder.HasIndex(r => r.RequestedByCustomerId);
        builder.HasIndex(r => r.Status);
        builder.HasIndex(r => r.TicketId);

        builder.HasOne<PaymentTransaction>().WithMany().HasForeignKey(r => r.PaymentTransactionId).IsRequired();
        builder.HasOne<Booking>().WithMany().HasForeignKey(r => r.BookingId).IsRequired();
        builder.HasOne<CustomerProfile>().WithMany().HasForeignKey(r => r.RequestedByCustomerId).IsRequired();
        // Forward-dep FK to the b15 tickets table (refinement-phase-6). Optional (nullable); NO ACTION so deleting
        // a ticket never cascades into money rows.
        builder.HasOne<Ticket>().WithMany().HasForeignKey(r => r.TicketId).OnDelete(DeleteBehavior.NoAction);

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