using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate;
using ColaFlow.Modules.ProjectManagement.Domain.ValueObjects;
using ColaFlow.Modules.ProjectManagement.Domain.Enums;

namespace ColaFlow.Modules.ProjectManagement.Infrastructure.Persistence.Configurations;

/// <summary>
/// EF Core configuration for Sprint entity
/// </summary>
public class SprintConfiguration : IEntityTypeConfiguration<Sprint>
{
    public void Configure(EntityTypeBuilder<Sprint> builder)
    {
        builder.ToTable("Sprints");

        // Primary Key
        builder.HasKey(s => s.Id);

        // Value Objects
        builder.Property(s => s.Id)
            .HasConversion(
                id => id.Value,
                value => SprintId.From(value))
            .ValueGeneratedNever();

        builder.Property(s => s.TenantId)
            .HasConversion(
                id => id.Value,
                value => TenantId.From(value))
            .IsRequired();

        builder.Property(s => s.ProjectId)
            .HasConversion(
                id => id.Value,
                value => ProjectId.From(value))
            .IsRequired();

        builder.Property(s => s.CreatedBy)
            .HasConversion(
                id => id.Value,
                value => UserId.From(value))
            .IsRequired();

        // Properties
        builder.Property(s => s.Name)
            .IsRequired()
            .HasMaxLength(200);

        builder.Property(s => s.Goal)
            .HasMaxLength(1000);

        builder.Property(s => s.StartDate)
            .IsRequired();

        builder.Property(s => s.EndDate)
            .IsRequired();

        builder.Property(s => s.Status)
            .IsRequired()
            .HasConversion(
                status => status.Name,
                name => SprintStatus.FromString(name))
            .HasMaxLength(20);

        builder.Property(s => s.CreatedAt)
            .IsRequired();

        builder.Property(s => s.UpdatedAt);

        // TaskIds as JSON column (PostgreSQL JSONB)
        builder.Property<List<TaskId>>("_taskIds")
            .HasColumnName("TaskIds")
            .HasColumnType("jsonb")
            .HasConversion(
                taskIds => System.Text.Json.JsonSerializer.Serialize(taskIds.Select(t => t.Value).ToList(), (System.Text.Json.JsonSerializerOptions?)null),
                json => System.Text.Json.JsonSerializer.Deserialize<List<Guid>>(json, (System.Text.Json.JsonSerializerOptions?)null)!
                    .Select(id => TaskId.From(id)).ToList());

        // Ignore read-only collection
        builder.Ignore(s => s.TaskIds);

        // Indexes for performance
        builder.HasIndex(s => new { s.TenantId, s.ProjectId })
            .HasDatabaseName("IX_Sprints_TenantId_ProjectId");

        builder.HasIndex(s => new { s.TenantId, s.Status })
            .HasDatabaseName("IX_Sprints_TenantId_Status");

        builder.HasIndex(s => s.StartDate)
            .HasDatabaseName("IX_Sprints_StartDate");

        builder.HasIndex(s => s.EndDate)
            .HasDatabaseName("IX_Sprints_EndDate");
    }
}
