using foodmarket.Domain.Inventory;
using Microsoft.EntityFrameworkCore;

namespace foodmarket.Infrastructure.Persistence.Configurations;

public static class InventoryConfigurations
{
    public static void ConfigureInventory(this ModelBuilder b)
    {
        b.Entity<Stock>(e =>
        {
            e.ToTable("stocks");
            e.Property(x => x.Quantity).HasPrecision(18, 4);
            e.Property(x => x.ReservedQuantity).HasPrecision(18, 4);
            e.Ignore(x => x.Available);

            e.HasOne(x => x.Product).WithMany().HasForeignKey(x => x.ProductId).OnDelete(DeleteBehavior.Cascade);
            e.HasOne(x => x.Store).WithMany().HasForeignKey(x => x.StoreId).OnDelete(DeleteBehavior.Cascade);

            e.HasIndex(x => new { x.OrganizationId, x.ProductId, x.StoreId }).IsUnique();
            e.HasIndex(x => new { x.OrganizationId, x.StoreId });
        });

        b.Entity<StockMovement>(e =>
        {
            e.ToTable("stock_movements");
            e.Property(x => x.Quantity).HasPrecision(18, 4);
            e.Property(x => x.UnitCost).HasPrecision(18, 4);
            e.Property(x => x.DocumentType).HasMaxLength(50).IsRequired();
            e.Property(x => x.DocumentNumber).HasMaxLength(50);
            e.Property(x => x.Notes).HasMaxLength(500);

            e.HasOne(x => x.Product).WithMany().HasForeignKey(x => x.ProductId).OnDelete(DeleteBehavior.Restrict);
            e.HasOne(x => x.Store).WithMany().HasForeignKey(x => x.StoreId).OnDelete(DeleteBehavior.Restrict);

            e.HasIndex(x => new { x.OrganizationId, x.ProductId, x.OccurredAt });
            e.HasIndex(x => new { x.OrganizationId, x.StoreId, x.OccurredAt });
            e.HasIndex(x => new { x.DocumentType, x.DocumentId });
        });

        b.Entity<Loss>(e =>
        {
            e.ToTable("losses");
            e.Property(x => x.Number).HasMaxLength(50).IsRequired();
            e.Property(x => x.Notes).HasMaxLength(1000);
            e.Property(x => x.Total).HasPrecision(18, 4);

            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.Loss).HasForeignKey(l => l.LossId).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.Reason });
        });

        b.Entity<LossLine>(e =>
        {
            e.ToTable("loss_lines");
            e.Property(x => x.Quantity).HasPrecision(18, 4);
            e.Property(x => x.UnitCost).HasPrecision(18, 4);
            e.Property(x => x.LineTotal).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<Transfer>(e =>
        {
            e.ToTable("transfers");
            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.Total).HasPrecision(18, 4);

            e.HasOne(x => x.FromStore).WithMany().HasForeignKey(x => x.FromStoreId).OnDelete(DeleteBehavior.Restrict);
            e.HasOne(x => x.ToStore).WithMany().HasForeignKey(x => x.ToStoreId).OnDelete(DeleteBehavior.Restrict);

            e.HasMany(x => x.Lines).WithOne(l => l.Transfer).HasForeignKey(l => l.TransferId).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 });
        });

        b.Entity<TransferLine>(e =>
        {
            e.ToTable("transfer_lines");
            e.Property(x => x.Quantity).HasPrecision(18, 4);
            e.Property(x => x.UnitCost).HasPrecision(18, 4);
            e.Property(x => x.LineTotal).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<InventoryDoc>(e =>
        {
            e.ToTable("inventories");
            e.UseXminAsConcurrencyToken();
            e.Ignore(x => x.Xmin);
            e.Property(x => x.Number).HasMaxLength(50).IsRequired();
            e.Property(x => x.Notes).HasMaxLength(1000);

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

            e.HasMany(x => x.Lines).WithOne(l => l.InventoryDoc).HasForeignKey(l => l.InventoryDocId).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 });
        });

        b.Entity<InventoryLine>(e =>
        {
            e.ToTable("inventory_lines");
            e.Property(x => x.BookQty).HasPrecision(18, 4);
            e.Property(x => x.ActualQty).HasPrecision(18, 4);
            e.Property(x => x.Diff).HasPrecision(18, 4);
            e.Property(x => x.UnitCost).HasPrecision(18, 4);

            e.HasOne(x => x.Product).WithMany().HasForeignKey(x => x.ProductId).OnDelete(DeleteBehavior.Restrict);

            e.HasIndex(x => new { x.OrganizationId, x.ProductId });
        });
    }
}
