using Intentor.Models;
using Microsoft.EntityFrameworkCore;

namespace Intentor.Data;

public sealed class IntentorDbContext : DbContext
{
    public IntentorDbContext(DbContextOptions<IntentorDbContext> options) : base(options) { }

    public DbSet<Space> Spaces => Set<Space>();
    public DbSet<Intent> Intents => Set<Intent>();
    public DbSet<IntentActivation> IntentActivations => Set<IntentActivation>();
    public DbSet<IntentRequirement> IntentRequirements => Set<IntentRequirement>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Space>()
            .HasMany(s => s.Intents)
            .WithOne(i => i.Space)
            .HasForeignKey(i => i.SpaceId)
            .OnDelete(DeleteBehavior.Cascade);

        modelBuilder.Entity<Intent>()
            .OwnsOne(i => i.Action, action =>
            {
                action.Property(a => a.Type).HasColumnName("ActionType");
                action.Property(a => a.EntityId).HasColumnName("ActionEntityId").HasMaxLength(255);
            });

        modelBuilder.Entity<IntentActivation>()
            .HasOne(a => a.Intent)
            .WithMany(i => i.Activations)
            .HasForeignKey(a => a.IntentId)
            .OnDelete(DeleteBehavior.Cascade);

        modelBuilder.Entity<IntentActivation>()
            .HasIndex(a => new { a.SpaceId, a.Until });

        modelBuilder.Entity<IntentActivation>()
            .HasIndex(a => new { a.SpaceId, a.CreatedAt });

        modelBuilder.Entity<IntentRequirement>()
            .HasKey(x => new { x.IntentId, x.RequiredIntentId });

        modelBuilder.Entity<IntentRequirement>()
            .HasOne(x => x.Intent)
            .WithMany(i => i.Requirements)
            .HasForeignKey(x => x.IntentId)
            .OnDelete(DeleteBehavior.Cascade);

        modelBuilder.Entity<IntentRequirement>()
            .HasOne(x => x.RequiredIntent)
            .WithMany(i => i.RequiredBy)
            .HasForeignKey(x => x.RequiredIntentId)
            .OnDelete(DeleteBehavior.Restrict);

        modelBuilder.Entity<Intent>()
            .HasIndex(i => new { i.SpaceId, i.Priority });

        modelBuilder.Entity<Intent>()
            .HasIndex(i => i.Name);
    }
}
