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

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using OrderService.Domain.AggregatesModel.OrderAggregate;

namespace OrderService.Infrastructure.EntityConfigurations;

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

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

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

        builder.Property<Guid>("_shopId")
            .HasColumnName("shop_id")
            .IsRequired();

        builder.Property<Guid?>("_customerId")
            .HasColumnName("customer_id");

        builder.Property<Guid?>("_tableId")
            .HasColumnName("table_id");

        builder.Property(o => o.StatusId)
            .HasColumnName("status_id")
            .IsRequired();

        builder.Property<decimal>("_totalAmount")
            .HasColumnName("total_amount")
            .HasColumnType("decimal(18,2)")
            .IsRequired();

        builder.Property<string?>("_notes")
            .HasColumnName("notes")
            .HasMaxLength(2000);

        builder.Property<DateTime>("_createdAt")
            .HasColumnName("created_at")
            .IsRequired();

        builder.Property<DateTime?>("_updatedAt")
            .HasColumnName("updated_at");

        builder.Property<decimal>("_discountAmount")
            .HasColumnName("discount_amount")
            .HasColumnType("decimal(18,2)");

        builder.Property<string?>("_discountType")
            .HasColumnName("discount_type")
            .HasMaxLength(50);

        builder.Property<string?>("_discountReference")
            .HasColumnName("discount_reference")
            .HasMaxLength(255);

        builder.Property<string?>("_paymentMethod")
            .HasColumnName("payment_method")
            .HasMaxLength(50);

        builder.Property<string?>("_transactionId")
            .HasColumnName("transaction_id")
            .HasMaxLength(255);

        builder.Property<decimal?>("_amountTendered")
            .HasColumnName("amount_tendered")
            .HasColumnType("decimal(18,2)");

        builder.Property<decimal?>("_changeAmount")
            .HasColumnName("change_amount")
            .HasColumnType("decimal(18,2)");

        builder.Property<string?>("_returnReason")
            .HasColumnName("return_reason")
            .HasMaxLength(1000);

        builder.Property<DateTime?>("_returnedAt")
            .HasColumnName("returned_at");

        builder.Property<bool>("_isReturn")
            .HasColumnName("is_return")
            .HasDefaultValue(false);

        builder.Property<Guid?>("_originalOrderId")
            .HasColumnName("original_order_id");

        // EN: OrderItems collection
        // VI: Collection OrderItems
        builder.OwnsMany(o => o.Items, orderItems =>
        {
            orderItems.ToTable("order_items");
            
            orderItems.WithOwner().HasForeignKey("OrderId");
            
            orderItems.Property<Guid>("OrderId")
                .HasColumnName("order_id");

            orderItems.HasKey(oi => oi.Id);
            
            orderItems.Property(x => x.Id)
                .HasColumnName("id")
                .ValueGeneratedNever();

            orderItems.Property<Guid>("_productId")
                .HasColumnName("product_id")
                .IsRequired();

            orderItems.Property<string>("_productName")
                .HasColumnName("product_name")
                .HasMaxLength(255)
                .IsRequired();

            orderItems.Property<string>("_productType")
                .HasColumnName("product_type")
                .HasMaxLength(50)
                .IsRequired();

            orderItems.Property<int>("_quantity")
                .HasColumnName("quantity")
                .IsRequired();

            orderItems.Property<decimal>("_unitPrice")
                .HasColumnName("unit_price")
                .HasColumnType("decimal(18,2)")
                .IsRequired();

            orderItems.Property<string>("_status")
                .HasColumnName("status")
                .HasMaxLength(50)
                .IsRequired();

            orderItems.Property<bool>("_trackInventory")
                .HasColumnName("track_inventory")
                .HasDefaultValue(true)
                .IsRequired();

            orderItems.Property<string?>("_metadata")
                .HasColumnName("metadata")
                .HasColumnType("jsonb");

            orderItems.Ignore(x => x.ProductId);
            orderItems.Ignore(x => x.ProductName);
            orderItems.Ignore(x => x.ProductType);
            orderItems.Ignore(x => x.Quantity);
            orderItems.Ignore(x => x.UnitPrice);
            orderItems.Ignore(x => x.TotalPrice);
            orderItems.Ignore(x => x.Status);
            orderItems.Ignore(x => x.TrackInventory);
            orderItems.Ignore(x => x.Metadata);
        });

        // EN: Indexes
        // VI: Indexes
        builder.HasIndex("_shopId").HasDatabaseName("ix_orders_shop_id");
        builder.HasIndex("_customerId").HasDatabaseName("ix_orders_customer_id");
        builder.HasIndex(o => o.StatusId).HasDatabaseName("ix_orders_status_id");
        builder.HasIndex("_createdAt").HasDatabaseName("ix_orders_created_at");
        builder.HasIndex("_originalOrderId").HasDatabaseName("ix_orders_original_order_id");

        // EN: Ignore calculated properties
        // VI: Bỏ qua các properties được tính toán
        builder.Ignore(o => o.ShopId);
        builder.Ignore(o => o.CustomerId);
        builder.Ignore(o => o.TableId);
        builder.Ignore(o => o.Status);
        builder.Ignore(o => o.TotalAmount);
        builder.Ignore(o => o.DiscountAmount);
        builder.Ignore(o => o.DiscountType);
        builder.Ignore(o => o.DiscountReference);
        builder.Ignore(o => o.PaymentMethod);
        builder.Ignore(o => o.TransactionId);
        builder.Ignore(o => o.AmountTendered);
        builder.Ignore(o => o.ChangeAmount);
        builder.Ignore(o => o.CreatedAt);
        builder.Ignore(o => o.UpdatedAt);
        builder.Ignore(o => o.ReturnReason);
        builder.Ignore(o => o.ReturnedAt);
        builder.Ignore(o => o.IsReturn);
        builder.Ignore(o => o.OriginalOrderId);
    }
}
