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

namespace Tiku.Infrastructure.Persistence.Configurations;

internal sealed class ContentAssetAccessEventConfiguration : IEntityTypeConfiguration<ContentAssetAccessEvent>
{
    public void Configure(EntityTypeBuilder<ContentAssetAccessEvent> builder)
    {
        builder.ConfigureEntity("content_asset_access_events");
        builder.HasAlternateKey(entity => new { entity.TenantId, entity.Id });
        builder.Property(entity => entity.ActorRole).HasSnakeCaseEnum();
        builder.Property(entity => entity.AccessType).HasSnakeCaseEnum();
        builder.Property(entity => entity.Visibility).HasMaxLength(50);
        builder.Property(entity => entity.AssetType).HasMaxLength(50);
        builder.Property(entity => entity.StorageProvider).HasMaxLength(50);
        builder.Property(entity => entity.Disposition).HasNullableSnakeCaseEnum();
        builder.Property(entity => entity.SignatureMode).HasMaxLength(100);
        builder.Property(entity => entity.Result).HasSnakeCaseEnum();
        builder.Property(entity => entity.DenyCode).HasMaxLength(100);
        builder.Property(entity => entity.IpAddress).HasMaxLength(100);
        builder.Property(entity => entity.UserAgent).HasMaxLength(1024);
        builder.Property(entity => entity.Metadata).IsJson("{}");
        builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()");
        builder.HasIndex(entity => new { entity.TenantId, entity.AssetId, entity.CreatedAt });
        builder.HasIndex(entity => new { entity.TenantId, entity.UserId, entity.CreatedAt })
            .HasFilter("user_id is not null");
        builder.HasIndex(entity => new { entity.TenantId, entity.AccessType, entity.Result, entity.CreatedAt });
        builder.ToTable(table => table.HasCheckConstraint("ck_content_asset_access_events_expiry",
            "expires_in_seconds is null or expires_in_seconds > 0"));
        builder.HasOne<Tenant>().WithMany().HasForeignKey(entity => entity.TenantId).OnDelete(DeleteBehavior.Cascade);
        builder.HasOne<ContentAsset>().WithMany()
            .HasForeignKey(entity => new { entity.TenantId, entity.AssetId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
            .OnDelete(DeleteBehavior.Restrict);
        builder.HasOne<User>().WithMany().HasForeignKey(entity => entity.UserId).OnDelete(DeleteBehavior.SetNull);
    }
}

internal sealed class
    ContentAssetSecurityScanEventConfiguration : IEntityTypeConfiguration<ContentAssetSecurityScanEvent>
{
    public void Configure(EntityTypeBuilder<ContentAssetSecurityScanEvent> builder)
    {
        builder.ConfigureEntity("content_asset_security_scan_events");
        builder.HasAlternateKey(entity => new { entity.TenantId, entity.Id });
        builder.Property(entity => entity.Provider).HasMaxLength(100);
        builder.Property(entity => entity.ScanStatus).HasSnakeCaseEnum();
        builder.Property(entity => entity.RiskLevel).HasSnakeCaseEnum();
        builder.Property(entity => entity.IssueCodes)
            .HasColumnType("text[]")
            .HasDefaultValueSql("'{}'::text[]");
        builder.Property(entity => entity.Details).IsJson("{}");
        builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()");
        builder.HasIndex(entity => new { entity.TenantId, entity.AssetId, entity.CreatedAt });
        builder.HasIndex(entity => new { entity.TenantId, entity.ScanStatus, entity.RiskLevel, entity.CreatedAt });
        builder.HasOne<Tenant>().WithMany().HasForeignKey(entity => entity.TenantId).OnDelete(DeleteBehavior.Cascade);
        builder.HasOne<ContentAsset>().WithMany()
            .HasForeignKey(entity => new { entity.TenantId, entity.AssetId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
            .OnDelete(DeleteBehavior.Restrict);
    }
}

internal sealed class TenantQuestionBankPreferenceConfiguration : IEntityTypeConfiguration<TenantQuestionBankPreference>
{
    public void Configure(EntityTypeBuilder<TenantQuestionBankPreference> builder)
    {
        builder.ConfigureTenantEntity("tenant_question_bank_preferences");
        builder.ConfigureTimestamps();
        builder.Property(entity => entity.Alias).HasMaxLength(300);
        builder.Property(entity => entity.NavigationLocation).HasMaxLength(100);
        builder.Property(entity => entity.Metadata).IsJson("{}");
        builder.HasIndex(entity => new
        {
            entity.TenantId,
            entity.QuestionBankOwnerTenantId,
            entity.QuestionBankId
        }).IsUnique();
        builder.HasOne<QuestionBank>().WithMany()
            .HasForeignKey(entity => new { entity.QuestionBankOwnerTenantId, entity.QuestionBankId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
            .OnDelete(DeleteBehavior.Restrict);
        builder.HasOne<User>().WithMany().HasForeignKey(entity => entity.CreatedBy).OnDelete(DeleteBehavior.SetNull);
        builder.HasOne<User>().WithMany().HasForeignKey(entity => entity.UpdatedBy).OnDelete(DeleteBehavior.SetNull);
    }
}

internal sealed class TenantQuestionReferenceConfiguration : IEntityTypeConfiguration<TenantQuestionReference>
{
    public void Configure(EntityTypeBuilder<TenantQuestionReference> builder)
    {
        builder.ConfigureTenantEntity("tenant_question_references");
        builder.ConfigureTimestamps();
        builder.Property(entity => entity.Source).HasSnakeCaseEnum();
        builder.HasAlternateKey(entity => new
        {
            entity.TenantId,
            entity.QuestionOwnerTenantId,
            entity.QuestionId
        });
        builder.HasOne<Question>().WithMany()
            .HasForeignKey(entity => new { entity.QuestionOwnerTenantId, entity.QuestionId })
            .HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
            .OnDelete(DeleteBehavior.Restrict);
        builder.HasOne<User>().WithMany().HasForeignKey(entity => entity.CreatedBy).OnDelete(DeleteBehavior.SetNull);
    }
}

internal sealed class AiRecommendationReportConfiguration : IEntityTypeConfiguration<AiRecommendationReport>
{
    public void Configure(EntityTypeBuilder<AiRecommendationReport> builder)
    {
        builder.ConfigureTenantEntity("ai_recommendation_reports");
        builder.ConfigureTimestamps();
        builder.Property(entity => entity.Status).HasSnakeCaseEnum();
        builder.Property(entity => entity.Provider).HasMaxLength(100);
        builder.Property(entity => entity.Model).HasMaxLength(100);
        builder.Property(entity => entity.PromptVersion).HasMaxLength(100);
        builder.Property(entity => entity.InputPayload).IsJson("{}");
        builder.Property(entity => entity.ContextPayload).IsJson("{}");
        builder.Property(entity => entity.ResultPayload).IsJson("{}");
        builder.HasIndex(entity => new { entity.TenantId, entity.UserId, entity.CreatedAt });
        builder.HasIndex(entity => new { entity.TenantId, entity.RegionId, entity.CreatedAt });
        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);
    }
}