using ColaFlow.Modules.Identity.Domain.Aggregates.Invitations;
using ColaFlow.Modules.Identity.Domain.Aggregates.Tenants;
using ColaFlow.Modules.Identity.Domain.Aggregates.Users;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

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

public class InvitationConfiguration : IEntityTypeConfiguration<Invitation>
{
    public void Configure(EntityTypeBuilder<Invitation> builder)
    {
        builder.ToTable("invitations");

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

        builder.Property(i => i.Id)
            .HasConversion(
                id => (Guid)id,
                value => InvitationId.Create(value))
            .HasColumnName("id");

        // Tenant ID (foreign key)
        builder.Property(i => i.TenantId)
            .HasConversion(
                id => (Guid)id,
                value => TenantId.Create(value))
            .IsRequired()
            .HasColumnName("tenant_id");

        // Invited By (User ID)
        builder.Property(i => i.InvitedBy)
            .HasConversion(
                id => (Guid)id,
                value => UserId.Create(value))
            .IsRequired()
            .HasColumnName("invited_by");

        // Email
        builder.Property(i => i.Email)
            .HasMaxLength(255)
            .IsRequired()
            .HasColumnName("email");

        // Role (enum stored as string)
        builder.Property(i => i.Role)
            .HasConversion<string>()
            .HasMaxLength(50)
            .IsRequired()
            .HasColumnName("role");

        // Security token hash
        builder.Property(i => i.TokenHash)
            .HasMaxLength(255)
            .IsRequired()
            .HasColumnName("token_hash");

        // Lifecycle timestamps
        builder.Property(i => i.ExpiresAt)
            .IsRequired()
            .HasColumnName("expires_at");

        builder.Property(i => i.AcceptedAt)
            .HasColumnName("accepted_at");

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

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

        // Indexes
        // Index for token lookup (invitation acceptance)
        builder.HasIndex(i => i.TokenHash)
            .IsUnique()
            .HasDatabaseName("ix_invitations_token_hash");

        // Index for tenant + email lookup (check for existing pending invitations)
        builder.HasIndex(i => new { i.TenantId, i.Email })
            .HasDatabaseName("ix_invitations_tenant_id_email");

        // Index for tenant + status lookup (get pending invitations)
        builder.HasIndex(i => new { i.TenantId, i.AcceptedAt, i.ExpiresAt })
            .HasDatabaseName("ix_invitations_tenant_id_status");

        // Unique constraint: Only one pending invitation per email per tenant
        // Note: This is enforced at application level due to NULL handling complexity
        // Could add a filtered unique index in migration if database supports it

        // Ignore domain events
        builder.Ignore(i => i.DomainEvents);
    }
}
