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

namespace Tiku.Infrastructure.Persistence.Configurations;

internal sealed class UserConfiguration : IEntityTypeConfiguration<User>
{
    public void Configure(EntityTypeBuilder<User> builder)
    {
        builder.ToTable("users");
        builder.HasKey(entity => entity.Id);
        builder.Property(entity => entity.Id).HasDefaultValueSql("gen_random_uuid()");
        builder.ConfigureTimestamps();

        builder.Property(entity => entity.LegacyId).HasMaxLength(64);
        builder.Property(entity => entity.UserName).HasMaxLength(100);
        builder.Property(entity => entity.NormalizedUserName).HasMaxLength(100);
        builder.Property(entity => entity.Email).HasColumnType("citext").HasMaxLength(320);
        builder.Property(entity => entity.NormalizedEmail).HasMaxLength(320);
        builder.Property(entity => entity.Phone).HasMaxLength(32);
        builder.Property(entity => entity.PhoneNumber).HasMaxLength(32);
        builder.Property(entity => entity.PasswordHash).HasMaxLength(1024);
        builder.Property(entity => entity.SecurityStamp).HasMaxLength(64);
        builder.Property(entity => entity.ConcurrencyStamp).HasMaxLength(64).IsConcurrencyToken();
        builder.Property(entity => entity.Name).HasMaxLength(200);
        builder.Property(entity => entity.AvatarUrl).HasMaxLength(2048);
        builder.Property(entity => entity.PrimaryRole).HasMaxLength(50);
        builder.Property(entity => entity.Status).HasSnakeCaseEnum();
        builder.Property(entity => entity.RawProfile).IsJson("{}");

        builder.HasIndex(entity => entity.LegacyId).IsUnique();
        builder.HasIndex(entity => entity.NormalizedUserName).IsUnique();
        builder.HasIndex(entity => entity.NormalizedEmail);
        builder.HasIndex(entity => entity.Phone).IsUnique();
    }
}

internal sealed class UserIdentityConfiguration : IEntityTypeConfiguration<UserIdentity>
{
    public void Configure(EntityTypeBuilder<UserIdentity> builder)
    {
        builder.ConfigureEntity("user_identities");
        builder.ConfigureTimestamps();

        builder.Property(entity => entity.Provider).HasMaxLength(50);
        builder.Property(entity => entity.ProviderSubject).HasMaxLength(255);
        builder.Property(entity => entity.UnionId).HasMaxLength(255);
        builder.Property(entity => entity.OpenId).HasMaxLength(255);
        builder.Property(entity => entity.Phone).HasMaxLength(32);
        builder.Property(entity => entity.Email).HasColumnType("citext").HasMaxLength(320);
        builder.HasIndex(entity => new { entity.Provider, entity.ProviderSubject }).IsUnique();
        builder.HasOne<User>()
            .WithMany()
            .HasForeignKey(entity => entity.UserId)
            .OnDelete(DeleteBehavior.Cascade);
    }
}

internal sealed class StudentProfileConfiguration : IEntityTypeConfiguration<StudentProfile>
{
    public void Configure(EntityTypeBuilder<StudentProfile> builder)
    {
        builder.ConfigureTenantEntity("student_profiles");
        builder.ConfigureTimestamps();

        builder.Property(entity => entity.LegacyUserId).HasMaxLength(64);
        builder.Property(entity => entity.AvatarPreset).HasMaxLength(32).HasDefaultValue("male");
        builder.Property(entity => entity.Stats).IsJson("{}");
        builder.Property(entity => entity.Progress).IsJson("{}");
        builder.Property(entity => entity.ModuleSelections).IsJson("{}");
        builder.Property(entity => entity.RecentActivities).IsJson("[]");

        builder.HasIndex(entity => new { entity.TenantId, entity.UserId }).IsUnique();

        builder.HasOne<User>()
            .WithMany()
            .HasForeignKey(entity => entity.UserId)
            .OnDelete(DeleteBehavior.Cascade);
        builder.HasOne<Region>()
            .WithMany()
            .HasForeignKey(entity => new { entity.TenantId, entity.RegionId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
            .OnDelete(DeleteBehavior.Restrict);
        builder.HasOne<School>()
            .WithMany()
            .HasForeignKey(entity => new { entity.TenantId, entity.SelectedSchoolId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
            .OnDelete(DeleteBehavior.Restrict);
        builder.HasOne<Major>()
            .WithMany()
            .HasForeignKey(entity => new { entity.TenantId, entity.SelectedMajorId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
            .OnDelete(DeleteBehavior.Restrict);
    }
}
