using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using TeleWave.Domain.Programming;

namespace TeleWave.Infrastructure.Persistence.Configurations;

public class GroupConfiguration : IEntityTypeConfiguration<Group>
{
    public void Configure(EntityTypeBuilder<Group> builder)
    {
        builder.Property(x => x.Name).IsRequired().HasMaxLength(256);
        builder.Property(x => x.Description).HasMaxLength(2048);

        // Правило набора хранится как jsonb: схему знает Application, а домен передаёт строку как есть.
        builder.Property(x => x.FilterJson).HasColumnType("jsonb");

        builder.Property(x => x.Mode).HasDefaultValue(GroupMode.Static);

        builder
            .HasMany(x => x.Items)
            .WithOne()
            .HasForeignKey(i => i.GroupId)
            .OnDelete(DeleteBehavior.Cascade);
        builder.Navigation(x => x.Items).UsePropertyAccessMode(PropertyAccessMode.Field);
    }
}

public class GroupItemConfiguration : IEntityTypeConfiguration<GroupItem>
{
    public void Configure(EntityTypeBuilder<GroupItem> builder)
    {
        builder.HasIndex(x => new { x.GroupId, x.Position });
        // Элемент входит в группу не более одного раза — иначе вес и порядок становятся неоднозначны.
        builder
            .HasIndex(x => new
            {
                x.GroupId,
                x.ElementKind,
                x.ElementId,
            })
            .IsUnique();

        // По этому индексу чистятся позиции при удалении шоу/коллекции: внешнего ключа на
        // полиморфную ссылку нет, удаление идёт командой.
        builder.HasIndex(x => new { x.ElementKind, x.ElementId });

        // Роль читается при каждом развороте динамической группы — отдельным индексом не выделяем,
        // выборка всегда идёт по группе целиком.
        builder.Property(x => x.Role).HasDefaultValue(GroupItemRole.Member);
    }
}
