using ERPCore.Domain.Entities;
using ERPCore.Domain.Enums;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace ERPCore.Infra.Persistence.Configurations;

public sealed class ItemConfiguration : IEntityTypeConfiguration<Item>
{
    public void Configure(EntityTypeBuilder<Item> builder)
    {
        builder.ToTable("items");
        builder.HasKey(i => i.ItemId);

        builder.Property(i => i.Sku).IsRequired().HasMaxLength(50);
        builder.HasIndex(i => i.Sku).IsUnique();

        builder.Property(i => i.Name).IsRequired().HasMaxLength(200);
        builder.Property(i => i.Description).HasMaxLength(1000);
        builder.Property(i => i.TaxClass).HasMaxLength(20);

        // Sales-only fixed selling price; nullable (null ⇒ sell at stock/FIFO value).
        builder.Property(i => i.SalePrice).HasPrecision(18, 4);

        // Optional content size (how much one stocked pack holds). All four are nullable
        // together: null ⇒ the item has no measurable content. The base pair is derived
        // server-side by ItemContent.Normalize and is only ever Ml or G.
        builder.Property(i => i.ContentQty).HasPrecision(18, 4);
        builder.Property(i => i.ContentBaseQty).HasPrecision(18, 4);
        builder.Property(i => i.ContentUnit)
            .HasConversion<string>().HasMaxLength(20);
        builder.Property(i => i.ContentBaseUnit)
            .HasConversion<string>().HasMaxLength(20);

        builder.Property(i => i.StockNature)
            .HasConversion<string>().HasMaxLength(20).IsRequired();
        builder.Property(i => i.TrackingMode)
            .HasConversion<string>().HasMaxLength(20).IsRequired();
        builder.Property(i => i.Warranty)
            .HasConversion<string>().HasMaxLength(20).IsRequired()
            .HasDefaultValue(Warranty.NonWarranty);
        builder.Property(i => i.Status)
            .HasConversion<string>().HasMaxLength(20).IsRequired()
            .HasDefaultValue(EntityStatus.Active);

        builder.Property(i => i.CreatedAt).IsRequired();

        // PostgreSQL xmin system column as the optimistic concurrency token (ETag).
        builder.Property(i => i.RowVersion).IsRowVersion();

        builder.HasOne(i => i.Category)
            .WithMany()
            .HasForeignKey(i => i.CategoryId)
            .OnDelete(DeleteBehavior.Restrict);

        builder.HasOne(i => i.SubCategory)
            .WithMany()
            .HasForeignKey(i => i.SubCategoryId)
            .OnDelete(DeleteBehavior.Restrict);

        builder.HasOne(i => i.Brand)
            .WithMany()
            .HasForeignKey(i => i.BrandId)
            .OnDelete(DeleteBehavior.Restrict);

        builder.HasOne(i => i.BaseUom)
            .WithMany()
            .HasForeignKey(i => i.BaseUomId)
            .OnDelete(DeleteBehavior.Restrict);

        builder.HasOne(i => i.DefaultVendor)
            .WithMany()
            .HasForeignKey(i => i.DefaultVendorId)
            .OnDelete(DeleteBehavior.Restrict);

        builder.HasIndex(i => i.Status);
        builder.HasIndex(i => i.CategoryId);
        builder.HasIndex(i => i.BrandId);
    }
}
