using Microsoft.EntityFrameworkCore;
using RpgRoller.Domain;

namespace RpgRoller.Data;

public sealed class RpgRollerDbContext(DbContextOptions<RpgRollerDbContext> options) : DbContext(options)
{
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<UserAccount>(entity =>
        {
            entity.HasKey(x => x.Id);
            entity.Property(x => x.Username).IsRequired().HasMaxLength(64);
            entity.Property(x => x.UsernameNormalized).IsRequired().HasMaxLength(64);
            entity.Property(x => x.PasswordHash).IsRequired();
            entity.Property(x => x.DisplayName).IsRequired().HasMaxLength(128);
            entity.Property(x => x.Roles).IsRequired().HasMaxLength(256);
            entity.HasIndex(x => x.UsernameNormalized).IsUnique();
        });

        modelBuilder.Entity<UserSession>(entity =>
        {
            entity.HasKey(x => x.Token);
            entity.Property(x => x.Token).HasMaxLength(64);
            entity.Property(x => x.CreatedAtUtc).IsRequired();
            entity.HasIndex(x => x.UserId);
        });

        modelBuilder.Entity<Campaign>(entity =>
        {
            entity.HasKey(x => x.Id);
            entity.Property(x => x.Name).IsRequired().HasMaxLength(128);
            entity.Property(x => x.Ruleset).HasConversion<string>().IsRequired();
            entity.Property(x => x.Version).IsRequired();
            entity.HasIndex(x => x.GmUserId);
        });

        modelBuilder.Entity<Character>(entity =>
        {
            entity.HasKey(x => x.Id);
            entity.Property(x => x.Name).IsRequired().HasMaxLength(128);
            entity.HasIndex(x => x.OwnerUserId);
            entity.HasIndex(x => x.CampaignId);
        });

        modelBuilder.Entity<Skill>(entity =>
        {
            entity.HasKey(x => x.Id);
            entity.Property(x => x.Name).IsRequired().HasMaxLength(128);
            entity.Property(x => x.DiceRollDefinition).IsRequired().HasMaxLength(128);
            entity.Property(x => x.WildDice).IsRequired();
            entity.Property(x => x.AllowFumble).IsRequired();
            entity.Property(x => x.FumbleRange).IsRequired(false);
            entity.Property(x => x.RolemasterAutoRetry).IsRequired().HasDefaultValue(false);
            entity.HasIndex(x => x.CharacterId);
            entity.HasIndex(x => x.SkillGroupId);
        });

        modelBuilder.Entity<SkillGroup>(entity =>
        {
            entity.HasKey(x => x.Id);
            entity.Property(x => x.Name).IsRequired().HasMaxLength(128);
            entity.Property(x => x.DiceRollDefinition).IsRequired().HasMaxLength(128);
            entity.Property(x => x.WildDice).IsRequired();
            entity.Property(x => x.AllowFumble).IsRequired();
            entity.Property(x => x.FumbleRange).IsRequired(false);
            entity.HasIndex(x => x.CharacterId);
        });

        modelBuilder.Entity<RollLogEntry>(entity =>
        {
            entity.HasKey(x => x.Id);
            entity.Property(x => x.Visibility).HasConversion<string>().IsRequired();
            entity.Property(x => x.Breakdown).IsRequired().HasMaxLength(256);
            entity.Property(x => x.Dice).IsRequired();
            entity.Property(x => x.TimestampUtc).IsRequired();
            entity.HasIndex(x => x.CampaignId);
            entity.HasIndex(x => x.RollerUserId);
            entity.HasIndex(x => x.SkillId);
            entity.HasIndex(x => x.CharacterId);
        });
    }

    public DbSet<UserAccount> Users => Set<UserAccount>();
    public DbSet<UserSession> Sessions => Set<UserSession>();
    public DbSet<Campaign> Campaigns => Set<Campaign>();
    public DbSet<Character> Characters => Set<Character>();
    public DbSet<Skill> Skills => Set<Skill>();
    public DbSet<SkillGroup> SkillGroups => Set<SkillGroup>();
    public DbSet<RollLogEntry> RollLogEntries => Set<RollLogEntry>();
}