using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Tiku.Domain.Catalog;
using Tiku.Domain.Content;
using Tiku.Domain.Identity;
using Tiku.Domain.QuestionBanks;

namespace Tiku.Infrastructure.Persistence.Configurations;

internal sealed class QuestionBankConfiguration : IEntityTypeConfiguration<QuestionBank>
{
    public void Configure(EntityTypeBuilder<QuestionBank> builder)
    {
        builder.ConfigureTenantEntity("question_banks");
        builder.ConfigureTimestamps();
        builder.Property(entity => entity.Name).HasMaxLength(300);
        builder.Property(entity => entity.Status).HasSnakeCaseEnum();
        builder.Property(entity => entity.Metadata).IsJson("{}");

        builder.HasOne<Region>().WithMany()
            .HasForeignKey(entity => new { entity.TenantId, entity.RegionId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
            .OnDelete(DeleteBehavior.Restrict);
        builder.HasOne<ContentEntry>().WithMany()
            .HasForeignKey(entity => new { entity.TenantId, entity.ContentEntryId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
            .OnDelete(DeleteBehavior.Restrict);
    }
}

internal sealed class QuestionConfiguration : IEntityTypeConfiguration<Question>
{
    public void Configure(EntityTypeBuilder<Question> builder)
    {
        builder.ConfigureTenantEntity("questions");
        builder.ConfigureTimestamps();
        builder.Property(entity => entity.LegacyId).HasMaxLength(64);
        builder.Property(entity => entity.LegacySubjectId).HasMaxLength(64);
        builder.Property(entity => entity.LegacyCategoryId).HasMaxLength(64);
        builder.Property(entity => entity.LegacyNodeId).HasMaxLength(64);
        builder.Property(entity => entity.Type).HasMaxLength(50);
        builder.Property(entity => entity.TypeLabel).HasMaxLength(100);
        builder.Property(entity => entity.Tags).IsJson("[]");
        builder.Property(entity => entity.ExamMarkers).IsJson("{}");
        builder.Property(entity => entity.MediaUrl).HasMaxLength(2048);
        builder.Property(entity => entity.Status).HasSnakeCaseEnum();
        builder.HasIndex(entity => new { entity.TenantId, entity.LegacyId }).IsUnique();

        builder.HasOne<QuestionBank>().WithMany()
            .HasForeignKey(entity => new { entity.TenantId, entity.QuestionBankId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
            .OnDelete(DeleteBehavior.Restrict);
        builder.HasOne<Subject>().WithMany()
            .HasForeignKey(entity => new { entity.TenantId, entity.SubjectId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
            .OnDelete(DeleteBehavior.Restrict);
        builder.HasOne<Category>().WithMany()
            .HasForeignKey(entity => new { entity.TenantId, entity.CategoryId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
            .OnDelete(DeleteBehavior.Restrict);
        builder.HasOne<ModuleNode>().WithMany()
            .HasForeignKey(entity => new { entity.TenantId, entity.NodeId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
            .OnDelete(DeleteBehavior.Restrict);
        builder.HasOne<ContentEntry>().WithMany()
            .HasForeignKey(entity => new { entity.TenantId, entity.EntryId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
            .OnDelete(DeleteBehavior.Restrict);
        builder.HasOne<ContentNode>().WithMany()
            .HasForeignKey(entity => new { entity.TenantId, entity.ContentNodeId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
            .OnDelete(DeleteBehavior.Restrict);
        builder.HasOne<QuestionCollection>().WithMany()
            .HasForeignKey(entity => new { entity.TenantId, entity.PrimaryCollectionId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
            .OnDelete(DeleteBehavior.Restrict);

        builder.HasOne<QuestionVersion>().WithMany()
            .HasForeignKey(entity => new { entity.TenantId, entity.Id, entity.CurrentVersionId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.QuestionId, entity.Id })
            .OnDelete(DeleteBehavior.Restrict);
    }
}

internal sealed class QuestionVersionConfiguration : IEntityTypeConfiguration<QuestionVersion>
{
    public void Configure(EntityTypeBuilder<QuestionVersion> builder)
    {
        builder.ConfigureEntity("question_versions");
        builder.HasAlternateKey(entity => new { entity.TenantId, entity.Id });
        builder.HasAlternateKey(entity => new { entity.TenantId, entity.QuestionId, entity.Id });

        builder.Property(entity => entity.Options).IsJson("[]");
        builder.Property(entity => entity.CorrectOptionIndices).IsJson("[]");
        builder.Property(entity => entity.SubQuestions).IsJson("[]");
        builder.Property(entity => entity.CodeLang).HasMaxLength(50);
        builder.Property(entity => entity.SourceHash).HasMaxLength(128);
        builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()");

        builder.HasIndex(entity => new { entity.TenantId, entity.QuestionId, entity.VersionNo }).IsUnique();
        builder.HasOne<Question>().WithMany()
            .HasForeignKey(entity => new { entity.TenantId, entity.QuestionId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
            .OnDelete(DeleteBehavior.Cascade);
        builder.HasOne<User>().WithMany()
            .HasForeignKey(entity => entity.CreatedBy)
            .OnDelete(DeleteBehavior.SetNull);
    }
}
