using foodmarket.Domain.Sales;
using Microsoft.EntityFrameworkCore;

namespace foodmarket.Infrastructure.Persistence.Configurations;

public static class SalesConfigurations
{
    public static void ConfigureSales(this ModelBuilder b)
    {
        b.Entity<RetailSale>(e =>
        {
            e.ToTable("retail_sales");
            e.UseXminAsConcurrencyToken();
            e.Ignore(x => x.Xmin);
            e.Property(x => x.Number).HasMaxLength(50).IsRequired();
            e.Property(x => x.Notes).HasMaxLength(1000);
            e.Property(x => x.Subtotal).HasPrecision(18, 4);
            e.Property(x => x.DiscountTotal).HasPrecision(18, 4);
            e.Property(x => x.Total).HasPrecision(18, 4);
            e.Property(x => x.PaidCash).HasPrecision(18, 4);
            e.Property(x => x.PaidCard).HasPrecision(18, 4);

            e.HasOne(x => x.Store).WithMany().HasForeignKey(x => x.StoreId).OnDelete(DeleteBehavior.Restrict);
            e.HasOne(x => x.RetailPoint).WithMany().HasForeignKey(x => x.RetailPointId).OnDelete(DeleteBehavior.Restrict);
            e.HasOne(x => x.Customer).WithMany().HasForeignKey(x => x.CustomerId).OnDelete(DeleteBehavior.Restrict);
            e.HasOne(x => x.Currency).WithMany().HasForeignKey(x => x.CurrencyId).OnDelete(DeleteBehavior.Restrict);
            e.HasOne(x => x.ReferenceSale).WithMany().HasForeignKey(x => x.ReferenceSaleId).OnDelete(DeleteBehavior.Restrict);

            e.HasMany(x => x.Lines).WithOne(l => l.RetailSale).HasForeignKey(l => l.RetailSaleId).OnDelete(DeleteBehavior.Cascade);

            e.HasIndex(x => new { x.OrganizationId, x.Number }).IsUnique();
            e.HasIndex(x => new { x.OrganizationId, x.Date });
            e.HasIndex(x => new { x.OrganizationId, x.Status });
            e.HasIndex(x => new { x.OrganizationId, x.CashierUserId });
            e.HasIndex(x => new { x.OrganizationId, x.IsReturn });
            e.HasIndex(x => x.ReferenceSaleId);
        });

        b.Entity<RetailSaleLine>(e =>
        {
            e.ToTable("retail_sale_lines");
            e.Property(x => x.Quantity).HasPrecision(18, 4);
            e.Property(x => x.UnitPrice).HasPrecision(18, 4);
            e.Property(x => x.Discount).HasPrecision(18, 4);
            e.Property(x => x.LineTotal).HasPrecision(18, 4);
            e.Property(x => x.VatPercent).HasPrecision(5, 2);
            e.Property(x => x.QtyReturned).HasPrecision(18, 4);

            e.HasOne(x => x.Product).WithMany().HasForeignKey(x => x.ProductId).OnDelete(DeleteBehavior.Restrict);
            e.HasIndex(x => new { x.OrganizationId, x.ProductId });
        });

        b.Entity<PosBatchAck>(e =>
        {
            e.ToTable("pos_batch_acks");
            e.Property(x => x.IdempotencyKey).IsRequired();
            e.Property(x => x.ResponseJson).HasColumnType("jsonb").IsRequired();
            // Уникальный индекс — гарантия идемпотентности на уровне БД:
            // вторая параллельная попытка вставить тот же ключ упадёт 23505,
            // контроллер прочитает уже сохранённый ResponseJson и вернёт его.
            e.HasIndex(x => new { x.OrganizationId, x.IdempotencyKey }).IsUnique();
            e.HasIndex(x => x.CreatedAt); // для фонового cleanup'а старых acks
        });

        b.Entity<Demand>(e =>
        {
            e.ToTable("demands");
            e.UseXminAsConcurrencyToken();
            e.Ignore(x => x.Xmin);
            e.Property(x => x.Number).HasMaxLength(50).IsRequired();
            e.Property(x => x.Notes).HasMaxLength(1000);
            e.Property(x => x.Subtotal).HasPrecision(18, 4);
            e.Property(x => x.DiscountTotal).HasPrecision(18, 4);
            e.Property(x => x.Total).HasPrecision(18, 4);
            e.Property(x => x.PaidAmount).HasPrecision(18, 4);

            e.HasOne(x => x.Customer).WithMany().HasForeignKey(x => x.CustomerId).OnDelete(DeleteBehavior.Restrict);
            e.HasOne(x => x.Store).WithMany().HasForeignKey(x => x.StoreId).OnDelete(DeleteBehavior.Restrict);
            e.HasOne(x => x.Currency).WithMany().HasForeignKey(x => x.CurrencyId).OnDelete(DeleteBehavior.Restrict);

            e.HasMany(x => x.Lines).WithOne(l => l.Demand).HasForeignKey(l => l.DemandId).OnDelete(DeleteBehavior.Cascade);

            e.HasIndex(x => new { x.OrganizationId, x.Number }).IsUnique();
            e.HasIndex(x => new { x.OrganizationId, x.Date });
            e.HasIndex(x => new { x.OrganizationId, x.Status });
            e.HasIndex(x => new { x.OrganizationId, x.CustomerId });
        });

        b.Entity<DemandLine>(e =>
        {
            e.ToTable("demand_lines");
            e.Property(x => x.Quantity).HasPrecision(18, 4);
            e.Property(x => x.UnitPrice).HasPrecision(18, 4);
            e.Property(x => x.Discount).HasPrecision(18, 4);
            e.Property(x => x.LineTotal).HasPrecision(18, 4);
            e.Property(x => x.VatPercent).HasPrecision(5, 2);

            e.HasOne(x => x.Product).WithMany().HasForeignKey(x => x.ProductId).OnDelete(DeleteBehavior.Restrict);
            e.HasIndex(x => new { x.OrganizationId, x.ProductId });
        });
    }
}
