using System.Text.Json;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using MktXService.Domain.AggregatesModel.CampaignAggregate;

namespace MktXService.Infrastructure.EntityConfigurations;

/// <summary>
/// EN: EF Core configuration for Campaign entity with JSONB support.
/// VI: Cấu hình EF Core cho entity Campaign với hỗ trợ JSONB.
/// </summary>
public class CampaignEntityTypeConfiguration : IEntityTypeConfiguration<Campaign>
{
    private static readonly JsonSerializerOptions JsonOptions = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        WriteIndented = false
    };

    public void Configure(EntityTypeBuilder<Campaign> builder)
    {
        // EN: Table name (snake_case for PostgreSQL)
        // VI: Tên bảng (snake_case cho PostgreSQL)
        builder.ToTable("campaigns");

        // EN: Primary key
        // VI: Khóa chính
        builder.HasKey(c => c.Id);

        // EN: Ignore domain events
        // VI: Bỏ qua domain events
        builder.Ignore(c => c.DomainEvents);

        // EN: Basic properties
        // VI: Các thuộc tính cơ bản
        builder.Property(c => c.Id)
            .HasColumnName("id")
            .IsRequired();

        builder.Property<Guid>("_merchantId")
            .HasColumnName("merchant_id")
            .IsRequired();

        builder.Property<string>("_name")
            .HasColumnName("name")
            .HasMaxLength(200)
            .IsRequired();

        builder.Property<string>("_type")
            .HasColumnName("type")
            .HasMaxLength(50)
            .IsRequired();

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

        builder.Property<Guid?>("_templateId")
            .HasColumnName("template_id");

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

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

        // ===========================================
        // EN: JSONB Columns for Complex Types
        // VI: Cột JSONB cho các kiểu phức tạp
        // ===========================================

        // EN: SegmentIds stored as JSONB array
        // VI: SegmentIds lưu dưới dạng mảng JSONB
        builder.Property<List<Guid>>("_segmentIds")
            .HasColumnName("segment_ids")
            .HasColumnType("jsonb")
            .HasConversion(
                v => JsonSerializer.Serialize(v, JsonOptions),
                v => JsonSerializer.Deserialize<List<Guid>>(v, JsonOptions) ?? new List<Guid>(),
                new ValueComparer<List<Guid>>(
                    (c1, c2) => c1!.SequenceEqual(c2!),
                    c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
                    c => c.ToList()));

        // EN: Schedule stored as JSONB (Value Object)
        // VI: Schedule lưu dưới dạng JSONB (Value Object)
        builder.Property<CampaignSchedule?>("_schedule")
            .HasColumnName("schedule")
            .HasColumnType("jsonb")
            .HasConversion(
                v => v == null ? null : JsonSerializer.Serialize(v, JsonOptions),
                v => v == null ? null : JsonSerializer.Deserialize<CampaignSchedule>(v, JsonOptions));

        // EN: Metrics stored as JSONB (Value Object)
        // VI: Metrics lưu dưới dạng JSONB (Value Object)
        builder.Property<CampaignMetrics>("_metrics")
            .HasColumnName("metrics")
            .HasColumnType("jsonb")
            .HasConversion(
                v => JsonSerializer.Serialize(v, JsonOptions),
                v => JsonSerializer.Deserialize<CampaignMetrics>(v, JsonOptions) 
                     ?? new CampaignMetrics(0, 0, 0, 0, 0, 0))
            .IsRequired();

        // ===========================================
        // EN: Relationships
        // VI: Quan hệ
        // ===========================================

        // EN: Status relationship (Enumeration pattern)
        // VI: Quan hệ với Status (pattern Enumeration)
        builder.HasOne(c => c.Status)
            .WithMany()
            .HasForeignKey(c => c.StatusId)
            .OnDelete(DeleteBehavior.Restrict);

        // ===========================================
        // EN: Indexes for commonly queried columns
        // VI: Index cho các cột hay truy vấn
        // ===========================================
        builder.HasIndex("_merchantId")
            .HasDatabaseName("ix_campaigns_merchant_id");

        builder.HasIndex(c => c.StatusId)
            .HasDatabaseName("ix_campaigns_status_id");

        builder.HasIndex("_createdAt")
            .HasDatabaseName("ix_campaigns_created_at")
            .IsDescending();

        // EN: Composite index for merchant + status queries
        // VI: Index kết hợp cho truy vấn merchant + status
        builder.HasIndex("_merchantId", "StatusId")
            .HasDatabaseName("ix_campaigns_merchant_status");
    }
}

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

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

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

        builder.Property(s => s.Name)
            .HasColumnName("name")
            .HasMaxLength(50)
            .IsRequired();

        // EN: Seed data for enumeration values
        // VI: Dữ liệu gốc cho các giá trị enumeration
        builder.HasData(
            CampaignStatus.Draft,
            CampaignStatus.Scheduled,
            CampaignStatus.Running,
            CampaignStatus.Paused,
            CampaignStatus.Completed,
            CampaignStatus.Cancelled
        );
    }
}
