// EN: Product entity configuration.
// VI: Cấu hình entity Product.

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using CatalogService.Domain.AggregatesModel.ProductAggregate;
using System.Text.Json;

namespace CatalogService.Infrastructure.EntityConfigurations;

/// <summary>
/// EN: EF Core configuration for Product entity.
/// VI: Cấu hình EF Core cho Product entity.
/// </summary>
public class ProductEntityTypeConfiguration : IEntityTypeConfiguration<Product>
{
    public void Configure(EntityTypeBuilder<Product> builder)
    {
        builder.ToTable("products");

        builder.HasKey(p => p.Id);

        builder.Property(p => p.Id)
            .HasColumnName("id")
            .ValueGeneratedNever();

        builder.Property(p => p.ShopId)
            .HasField("_shopId")
            .HasColumnName("shop_id")
            .IsRequired();

        builder.Property(p => p.Name)
            .HasField("_name")
            .HasColumnName("name")
            .HasMaxLength(255)
            .IsRequired();

        builder.Property(p => p.Description)
            .HasField("_description")
            .HasColumnName("description")
            .HasMaxLength(2000);

        builder.Property(p => p.Price)
            .HasField("_price")
            .HasColumnName("price")
            .HasColumnType("decimal(18,2)")
            .IsRequired();

        builder.Property(p => p.TypeId)
            .HasColumnName("type_id")
            .IsRequired();

        // EN: JSONB configuration for polymorphic attributes.
        //     Use value converter + comparer so EF Core can track changes on JsonDocument.
        // VI: Cấu hình JSONB cho attributes đa hình.
        //     Dùng value converter + comparer để EF Core theo dõi thay đổi trên JsonDocument.
        builder.Property(p => p.Attributes)
            .HasField("_attributes")
            .HasColumnName("attributes")
            .HasColumnType("jsonb")
            .HasConversion(
                v => v != null ? v.RootElement.GetRawText() : null,
                v => v != null ? JsonDocument.Parse(v, default) : null)
            .Metadata.SetValueComparer(
                new Microsoft.EntityFrameworkCore.ChangeTracking.ValueComparer<JsonDocument?>(
                    (a, b) => (a == null && b == null) || (a != null && b != null && a.RootElement.GetRawText() == b.RootElement.GetRawText()),
                    v => v != null ? v.RootElement.GetRawText().GetHashCode() : 0,
                    v => v != null ? JsonDocument.Parse(v.RootElement.GetRawText(), default) : null));

        builder.Property(p => p.ImageUrl)
            .HasField("_imageUrl")
            .HasColumnName("image_url")
            .HasMaxLength(500);

        builder.Property(p => p.Sku)
            .HasField("_sku")
            .HasColumnName("sku")
            .HasMaxLength(100);

        builder.Property(p => p.Barcode)
            .HasField("_barcode")
            .HasColumnName("barcode")
            .HasMaxLength(100);

        builder.Property(p => p.CategoryId)
            .HasField("_categoryId")
            .HasColumnName("category_id");

        builder.Property(p => p.IsActive)
            .HasField("_isActive")
            .HasColumnName("is_active")
            .HasDefaultValue(true);

        builder.Property(p => p.CreatedAt)
            .HasField("_createdAt")
            .HasColumnName("created_at")
            .IsRequired();

        builder.Property(p => p.UpdatedAt)
            .HasField("_updatedAt")
            .HasColumnName("updated_at");

        // EN: Indexes
        // VI: Indexes
        builder.HasIndex(p => p.ShopId).HasDatabaseName("ix_products_shop_id");
        builder.HasIndex(p => p.TypeId).HasDatabaseName("ix_products_type_id");
        builder.HasIndex(p => p.Sku).HasDatabaseName("ix_products_sku");
        builder.HasIndex(p => p.Barcode).HasDatabaseName("ix_products_barcode");
        builder.HasIndex(p => p.IsActive).HasDatabaseName("ix_products_is_active");
        builder.HasIndex(p => p.CategoryId).HasDatabaseName("ix_products_category_id");

        // EN: TypeId is a plain FK column — no navigation property to ProductType.
        //     Type name is resolved from Enumeration in query handlers.
        // VI: TypeId là cột FK thuần — không có navigation property đến ProductType.
        //     Tên Type được resolve từ Enumeration trong query handlers.
    }
}
