using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using ChatService.Domain.AggregatesModel.ConversationAggregate;

namespace ChatService.Infrastructure.EntityConfigurations;

/// <summary>
/// EN: Entity configuration for Conversation aggregate root.
/// VI: Cấu hình entity cho Conversation aggregate root.
/// </summary>
public class ConversationEntityTypeConfiguration : IEntityTypeConfiguration<Conversation>
{
    public void Configure(EntityTypeBuilder<Conversation> builder)
    {
        builder.ToTable("conversations");

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

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

        builder.Property(c => c.Name)
            .HasColumnName("name")
            .HasMaxLength(256);

        builder.Property(c => c.AvatarUrl)
            .HasColumnName("avatar_url")
            .HasMaxLength(2048);

        builder.Property(c => c.CreatedAt)
            .HasColumnName("created_at")
            .IsRequired();

        builder.Property(c => c.UpdatedAt)
            .HasColumnName("updated_at")
            .IsRequired();

        builder.Property(c => c.LastMessageId)
            .HasColumnName("last_message_id");

        builder.Property(c => c.LastMessageAt)
            .HasColumnName("last_message_at");

        // EN: Configure Type as navigation to Enumeration
        // VI: Cấu hình Type như navigation đến Enumeration
        builder.Property<int>("_typeId")
            .UsePropertyAccessMode(PropertyAccessMode.Field)
            .HasColumnName("type_id")
            .IsRequired();

        builder.HasOne(c => c.Type)
            .WithMany()
            .HasForeignKey("_typeId");

        // EN: Configure Participants collection
        // VI: Cấu hình collection Participants
        var participantsNav = builder.Metadata.FindNavigation(nameof(Conversation.Participants));
        participantsNav?.SetPropertyAccessMode(PropertyAccessMode.Field);

        builder.HasMany(c => c.Participants)
            .WithOne()
            .HasForeignKey(p => p.ConversationId)
            .OnDelete(DeleteBehavior.Cascade);

        // EN: Configure Messages collection
        // VI: Cấu hình collection Messages
        var messagesNav = builder.Metadata.FindNavigation(nameof(Conversation.Messages));
        messagesNav?.SetPropertyAccessMode(PropertyAccessMode.Field);

        builder.HasMany(c => c.Messages)
            .WithOne()
            .HasForeignKey(m => m.ConversationId)
            .OnDelete(DeleteBehavior.Cascade);

        // EN: Index for ordering conversations
        // VI: Index để sắp xếp conversations
        builder.HasIndex(c => c.LastMessageAt);
    }
}

/// <summary>
/// EN: Entity configuration for ConversationParticipant entity.
/// VI: Cấu hình entity cho ConversationParticipant entity.
/// </summary>
public class ConversationParticipantEntityTypeConfiguration : IEntityTypeConfiguration<ConversationParticipant>
{
    public void Configure(EntityTypeBuilder<ConversationParticipant> builder)
    {
        builder.ToTable("conversation_participants");

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

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

        builder.Property(p => p.ConversationId)
            .HasColumnName("conversation_id")
            .IsRequired();

        builder.Property(p => p.UserId)
            .HasColumnName("user_id")
            .IsRequired();

        builder.Property(p => p.JoinedAt)
            .HasColumnName("joined_at")
            .IsRequired();

        builder.Property(p => p.LastReadAt)
            .HasColumnName("last_read_at");

        builder.Property(p => p.IsAdmin)
            .HasColumnName("is_admin")
            .IsRequired();

        builder.Property(p => p.IsMuted)
            .HasColumnName("is_muted")
            .IsRequired();

        builder.Property(p => p.LeftAt)
            .HasColumnName("left_at");

        // EN: Unique index for user per conversation
        // VI: Index unique cho user trong mỗi conversation
        builder.HasIndex(p => new { p.ConversationId, p.UserId });

        // EN: Index for finding user's conversations
        // VI: Index để tìm conversations của user
        builder.HasIndex(p => p.UserId);
    }
}

/// <summary>
/// EN: Entity configuration for Message entity.
/// VI: Cấu hình entity cho Message entity.
/// </summary>
public class MessageEntityTypeConfiguration : IEntityTypeConfiguration<Message>
{
    public void Configure(EntityTypeBuilder<Message> builder)
    {
        builder.ToTable("messages");

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

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

        builder.Property(m => m.ConversationId)
            .HasColumnName("conversation_id")
            .IsRequired();

        builder.Property(m => m.SenderId)
            .HasColumnName("sender_id")
            .IsRequired();

        // EN: Encrypted content - server cannot read this
        // VI: Nội dung đã mã hóa - server không thể đọc được
        builder.Property(m => m.EncryptedContent)
            .HasColumnName("encrypted_content")
            .IsRequired();

        builder.Property(m => m.Nonce)
            .HasColumnName("nonce")
            .HasMaxLength(256)
            .IsRequired();

        builder.Property(m => m.AuthTag)
            .HasColumnName("auth_tag")
            .HasMaxLength(256);

        builder.Property(m => m.CreatedAt)
            .HasColumnName("created_at")
            .IsRequired();

        builder.Property(m => m.UpdatedAt)
            .HasColumnName("updated_at");

        builder.Property(m => m.Metadata)
            .HasColumnName("metadata");

        builder.Property(m => m.ReplyToMessageId)
            .HasColumnName("reply_to_message_id");

        // EN: Configure Type as navigation to Enumeration
        // VI: Cấu hình Type như navigation đến Enumeration
        builder.Property<int>("_typeId")
            .UsePropertyAccessMode(PropertyAccessMode.Field)
            .HasColumnName("type_id")
            .IsRequired();

        builder.HasOne(m => m.Type)
            .WithMany()
            .HasForeignKey("_typeId");

        // EN: Configure Status as navigation to Enumeration
        // VI: Cấu hình Status như navigation đến Enumeration
        builder.Property<int>("_statusId")
            .UsePropertyAccessMode(PropertyAccessMode.Field)
            .HasColumnName("status_id")
            .IsRequired();

        builder.HasOne(m => m.Status)
            .WithMany()
            .HasForeignKey("_statusId");

        // EN: Indexes for querying messages
        // VI: Indexes để query messages
        builder.HasIndex(m => new { m.ConversationId, m.CreatedAt });
        builder.HasIndex(m => m.SenderId);
    }
}

/// <summary>
/// EN: Entity configuration for ConversationType enumeration.
/// VI: Cấu hình entity cho ConversationType enumeration.
/// </summary>
public class ConversationTypeEntityTypeConfiguration : IEntityTypeConfiguration<ConversationType>
{
    public void Configure(EntityTypeBuilder<ConversationType> builder)
    {
        builder.ToTable("conversation_types");

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

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

        builder.Property(t => t.Name)
            .HasColumnName("name")
            .HasMaxLength(200)
            .IsRequired();

        builder.HasData(
            ConversationType.Direct,
            ConversationType.Group
        );
    }
}

/// <summary>
/// EN: Entity configuration for MessageStatus enumeration.
/// VI: Cấu hình entity cho MessageStatus enumeration.
/// </summary>
public class MessageStatusEntityTypeConfiguration : IEntityTypeConfiguration<MessageStatus>
{
    public void Configure(EntityTypeBuilder<MessageStatus> builder)
    {
        builder.ToTable("message_statuses");

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

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

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

        builder.HasData(
            MessageStatus.Sent,
            MessageStatus.Delivered,
            MessageStatus.Read,
            MessageStatus.Failed
        );
    }
}

/// <summary>
/// EN: Entity configuration for MessageType enumeration.
/// VI: Cấu hình entity cho MessageType enumeration.
/// </summary>
public class MessageTypeEntityTypeConfiguration : IEntityTypeConfiguration<MessageType>
{
    public void Configure(EntityTypeBuilder<MessageType> builder)
    {
        builder.ToTable("message_types");

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

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

        builder.Property(t => t.Name)
            .HasColumnName("name")
            .HasMaxLength(200)
            .IsRequired();

        builder.HasData(
            MessageType.Text,
            MessageType.Image,
            MessageType.File,
            MessageType.Voice,
            MessageType.System
        );
    }
}
