using CMSMicroservice.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace CMSMicroservice.Infrastructure.Persistence.Configurations;

/// <summary>
/// تنظیمات Entity Framework برای حرکات انبار
/// </summary>
public class StockMovementConfiguration : IEntityTypeConfiguration<StockMovement>
{
    public void Configure(EntityTypeBuilder<StockMovement> builder)
    {
        // ========== تنظیمات پایه ==========
        builder.HasQueryFilter(s => !s.IsDeleted);
        builder.Ignore(entity => entity.DomainEvents);
        builder.HasKey(entity => entity.Id);
        builder.Property(entity => entity.Id).UseIdentityColumn();
        
        // ========== فیلدهای اصلی ==========
        
        // نوع حرکت (enum به int)
        builder.Property(e => e.MovementType)
            .IsRequired()
            .HasConversion<int>();
        
        // مقدار تغییر (می‌تواند منفی باشد)
        builder.Property(e => e.Quantity)
            .IsRequired();
        
        // موجودی قبل و بعد
        builder.Property(e => e.QuantityBefore)
            .IsRequired();
        
        builder.Property(e => e.QuantityAfter)
            .IsRequired();
        
        // ========== فیلدهای اختیاری ==========
        
        // شناسه سفارش معمولی
        builder.Property(e => e.OrderId)
            .IsRequired(false);
        
        // شناسه سفارش تخفیفی
        builder.Property(e => e.DiscountOrderId)
            .IsRequired(false);
        
        // شماره مرجع
        builder.Property(e => e.ReferenceNumber)
            .IsRequired(false)
            .HasMaxLength(100);
        
        // یادداشت
        builder.Property(e => e.Note)
            .IsRequired(false)
            .HasMaxLength(500);
        
        // کاربر انجام‌دهنده
        builder.Property(e => e.PerformedByUserId)
            .IsRequired(false);
        
        // ========== روابط ==========
        
        // رابطه با InventoryItem (اجباری)
        builder.HasOne(e => e.InventoryItem)
            .WithMany(i => i.StockMovements)
            .HasForeignKey(e => e.InventoryItemId)
            .IsRequired()
            .OnDelete(DeleteBehavior.Cascade);
        
        // ========== Index ها ==========
        
        // Index روی InventoryItemId برای جستجوی حرکات یک آیتم
        builder.HasIndex(e => e.InventoryItemId)
            .HasDatabaseName("IX_StockMovements_InventoryItemId");
        
        // Index روی MovementType برای فیلتر بر اساس نوع حرکت
        builder.HasIndex(e => e.MovementType)
            .HasDatabaseName("IX_StockMovements_MovementType");
        
        // Index روی Created برای مرتب‌سازی زمانی
        builder.HasIndex(e => e.Created)
            .HasDatabaseName("IX_StockMovements_Created");
        
        // Index ترکیبی برای گزارش‌گیری
        builder.HasIndex(e => new { e.InventoryItemId, e.MovementType, e.Created })
            .HasDatabaseName("IX_StockMovements_Item_Type_Date");
        
        // Index روی OrderId برای ردیابی حرکات مرتبط با سفارش
        builder.HasIndex(e => e.OrderId)
            .HasDatabaseName("IX_StockMovements_OrderId")
            .HasFilter("[OrderId] IS NOT NULL");
        
        // Index روی DiscountOrderId برای ردیابی حرکات مرتبط با سفارش تخفیفی
        builder.HasIndex(e => e.DiscountOrderId)
            .HasDatabaseName("IX_StockMovements_DiscountOrderId")
            .HasFilter("[DiscountOrderId] IS NOT NULL");
        
        // Index روی ReferenceNumber برای جستجوی سریع با شماره مرجع
        builder.HasIndex(e => e.ReferenceNumber)
            .HasDatabaseName("IX_StockMovements_ReferenceNumber")
            .HasFilter("[ReferenceNumber] IS NOT NULL");
        
        // ========== محدودیت‌ها ==========
        
        // محدودیت: QuantityAfter باید برابر QuantityBefore + Quantity باشد
        builder.HasCheckConstraint("CK_StockMovement_QuantityAfter_Calculation", 
            "QuantityAfter = QuantityBefore + Quantity");
        
        // محدودیت: QuantityBefore و QuantityAfter نمی‌توانند منفی باشند
        builder.HasCheckConstraint("CK_StockMovement_QuantityBefore_NonNegative", 
            "QuantityBefore >= 0");
        
        builder.HasCheckConstraint("CK_StockMovement_QuantityAfter_NonNegative", 
            "QuantityAfter >= 0");
    }
}