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

namespace MktXService.Infrastructure.EntityConfigurations;

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

    public void Configure(EntityTypeBuilder<AutomationFlow> builder)
    {
        builder.ToTable("automation_flows");

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

        builder.Ignore(f => f.DomainEvents);

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

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

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

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

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

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

        // ===========================================
        // EN: JSONB Column for FlowTrigger (Value Object)
        // VI: Cột JSONB cho FlowTrigger (Value Object)
        // ===========================================
        builder.Property<FlowTrigger>("_trigger")
            .HasColumnName("trigger")
            .HasColumnType("jsonb")
            .HasConversion(
                v => JsonSerializer.Serialize(v, JsonOptions),
                v => JsonSerializer.Deserialize<FlowTrigger>(v, JsonOptions)!)
            .IsRequired();

        // ===========================================
        // EN: Relationships
        // VI: Quan hệ
        // ===========================================
        builder.HasOne(f => f.Status)
            .WithMany()
            .HasForeignKey(f => f.StatusId)
            .OnDelete(DeleteBehavior.Restrict);

        // EN: One-to-many with FlowNodes
        // VI: Quan hệ một-nhiều với FlowNodes
        builder.HasMany(f => f.Nodes)
            .WithOne()
            .HasForeignKey(n => n.FlowId)
            .OnDelete(DeleteBehavior.Cascade);

        // EN: One-to-many with FlowConnections
        // VI: Quan hệ một-nhiều với FlowConnections
        builder.HasMany(f => f.Connections)
            .WithOne()
            .HasForeignKey(c => c.FlowId)
            .OnDelete(DeleteBehavior.Cascade);

        // ===========================================
        // EN: Indexes
        // VI: Các index
        // ===========================================
        builder.HasIndex("_merchantId")
            .HasDatabaseName("ix_automation_flows_merchant_id");

        builder.HasIndex(f => f.StatusId)
            .HasDatabaseName("ix_automation_flows_status_id");
    }
}

/// <summary>
/// EN: EF Core configuration for FlowNode entity.
/// VI: Cấu hình EF Core cho entity FlowNode.
/// </summary>
public class FlowNodeEntityTypeConfiguration : IEntityTypeConfiguration<FlowNode>
{
    private static readonly JsonSerializerOptions JsonOptions = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        WriteIndented = false
    };

    public void Configure(EntityTypeBuilder<FlowNode> builder)
    {
        builder.ToTable("flow_nodes");

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

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

        builder.Property(n => n.FlowId)
            .HasColumnName("flow_id")
            .IsRequired();

        builder.Property(n => n.Type)
            .HasColumnName("type")
            .HasMaxLength(50)
            .IsRequired();

        builder.Property(n => n.PositionX)
            .HasColumnName("position_x");

        builder.Property(n => n.PositionY)
            .HasColumnName("position_y");

        // EN: Config stored as JSONB
        // VI: Config lưu dưới dạng JSONB
        builder.Property(n => n.Config)
            .HasColumnName("config")
            .HasColumnType("jsonb")
            .HasConversion(
                v => v == null ? null : JsonSerializer.Serialize(v, JsonOptions),
                v => v == null ? null : JsonSerializer.Deserialize<Dictionary<string, object>>(v, JsonOptions));

        builder.HasIndex(n => n.FlowId)
            .HasDatabaseName("ix_flow_nodes_flow_id");
    }
}

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

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

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

        builder.Property(c => c.FlowId)
            .HasColumnName("flow_id")
            .IsRequired();

        builder.Property(c => c.FromNodeId)
            .HasColumnName("from_node_id")
            .IsRequired();

        builder.Property(c => c.ToNodeId)
            .HasColumnName("to_node_id")
            .IsRequired();

        builder.Property(c => c.Condition)
            .HasColumnName("condition")
            .HasMaxLength(500);

        builder.HasIndex(c => c.FlowId)
            .HasDatabaseName("ix_flow_connections_flow_id");
    }
}

/// <summary>
/// EN: EF Core configuration for FlowStatus enumeration.
/// VI: Cấu hình EF Core cho enumeration FlowStatus.
/// </summary>
public class FlowStatusEntityTypeConfiguration : IEntityTypeConfiguration<FlowStatus>
{
    public void Configure(EntityTypeBuilder<FlowStatus> builder)
    {
        builder.ToTable("flow_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();

        builder.HasData(
            FlowStatus.Draft,
            FlowStatus.Active,
            FlowStatus.Inactive
        );
    }
}
