using Microsoft.EntityFrameworkCore;
using NexusIdentity.Api.Models;

namespace NexusIdentity.Api.Data;

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

    public DbSet<UserEntity> Users => Set<UserEntity>();
    public DbSet<RefreshTokenEntity> RefreshTokens => Set<RefreshTokenEntity>();
    public DbSet<RoleEntity> Roles => Set<RoleEntity>();
    public DbSet<AuditLogEntity> AuditLogs => Set<AuditLogEntity>();
    public DbSet<OrganizationEntity> Organizations => Set<OrganizationEntity>();
    public DbSet<DeviceEntity> Devices => Set<DeviceEntity>();
    public DbSet<DeviceTrustEntity> DeviceTrust => Set<DeviceTrustEntity>();
    public DbSet<EnrollmentRequestEntity> EnrollmentRequests => Set<EnrollmentRequestEntity>();
    public DbSet<PolicyEntity> Policies => Set<PolicyEntity>();
    public DbSet<DevicePresenceEntity> DevicePresence => Set<DevicePresenceEntity>();
    public DbSet<DeviceHeartbeatEntity> DeviceHeartbeats => Set<DeviceHeartbeatEntity>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<UserEntity>(entity =>
        {
            entity.HasKey(x => x.Id);
            entity.HasIndex(x => x.Email).IsUnique();
            entity.Property(x => x.Email).HasMaxLength(256);
            entity.Property(x => x.DisplayName).HasMaxLength(128);
            entity.Property(x => x.Theme).HasMaxLength(16);
            entity.Property(x => x.Role).HasMaxLength(64);
            entity.Property(x => x.OrganizationId).HasMaxLength(64);
            entity.HasOne(x => x.Organization).WithMany(o => o.Users).HasForeignKey(x => x.OrganizationId);
        });

        modelBuilder.Entity<RefreshTokenEntity>(entity =>
        {
            entity.HasKey(x => x.Id);
            entity.HasIndex(x => x.TokenHash).IsUnique();
            entity.HasOne(x => x.User).WithMany().HasForeignKey(x => x.UserId);
        });

        modelBuilder.Entity<RoleEntity>(entity =>
        {
            entity.HasKey(x => x.Id);
            entity.HasIndex(x => x.Name).IsUnique();
            entity.Property(x => x.Name).HasMaxLength(64);
        });

        modelBuilder.Entity<AuditLogEntity>(entity =>
        {
            entity.HasKey(x => x.Id);
            entity.Property(x => x.EventType).HasMaxLength(64);
            entity.Property(x => x.Message).HasMaxLength(2048);
            entity.HasOne(x => x.User).WithMany().HasForeignKey(x => x.UserId);
        });

        modelBuilder.Entity<OrganizationEntity>(entity =>
        {
            entity.HasKey(x => x.Id);
            entity.Property(x => x.Id).HasMaxLength(64);
            entity.Property(x => x.Name).HasMaxLength(256);
        });

        modelBuilder.Entity<DeviceEntity>(entity =>
        {
            entity.HasKey(x => x.DeviceId);
            entity.Property(x => x.DeviceId).HasMaxLength(128);
            entity.Property(x => x.ComputerName).HasMaxLength(128);
            entity.Property(x => x.FriendlyName).HasMaxLength(128);
            entity.Property(x => x.Owner).HasMaxLength(128);
            entity.Property(x => x.Os).HasMaxLength(64);
            entity.Property(x => x.EnrollmentStatus).HasMaxLength(32);
            entity.Property(x => x.LastHealth).HasMaxLength(32);
            entity.HasOne(x => x.Organization).WithMany(o => o.Devices).HasForeignKey(x => x.OrganizationId);
            entity.HasOne(x => x.User).WithMany().HasForeignKey(x => x.UserId);
        });

        modelBuilder.Entity<DeviceTrustEntity>(entity =>
        {
            entity.HasKey(x => x.DeviceId);
            entity.Property(x => x.DeviceId).HasMaxLength(128);
            entity.Property(x => x.Status).HasMaxLength(32);
            entity.Property(x => x.Reason).HasMaxLength(512);
            entity.HasOne(x => x.Device).WithOne(d => d.Trust).HasForeignKey<DeviceTrustEntity>(x => x.DeviceId);
        });

        modelBuilder.Entity<EnrollmentRequestEntity>(entity =>
        {
            entity.HasKey(x => x.Id);
            entity.Property(x => x.DeviceId).HasMaxLength(128);
            entity.Property(x => x.OrganizationId).HasMaxLength(64);
            entity.Property(x => x.UserName).HasMaxLength(128);
            entity.Property(x => x.DeviceFriendlyName).HasMaxLength(128);
            entity.Property(x => x.ComputerName).HasMaxLength(128);
            entity.Property(x => x.Status).HasMaxLength(32);
            entity.HasOne(x => x.Organization).WithMany().HasForeignKey(x => x.OrganizationId);
            entity.HasIndex(x => x.DeviceId);
            entity.HasIndex(x => x.Status);
        });

        modelBuilder.Entity<PolicyEntity>(entity =>
        {
            entity.HasKey(x => x.Id);
            entity.Property(x => x.Id).HasMaxLength(64);
            entity.Property(x => x.Name).HasMaxLength(128);
            entity.Property(x => x.Scope).HasMaxLength(32);
            entity.Property(x => x.Summary).HasMaxLength(512);
            entity.HasOne(x => x.Organization).WithMany(o => o.Policies).HasForeignKey(x => x.OrganizationId);
        });

        modelBuilder.Entity<DevicePresenceEntity>(entity =>
        {
            entity.HasKey(x => x.DeviceId);
            entity.Property(x => x.DeviceId).HasMaxLength(128);
            entity.Property(x => x.UserName).HasMaxLength(128);
            entity.Property(x => x.OrganizationName).HasMaxLength(256);
            entity.Property(x => x.AgentVersion).HasMaxLength(32);
            entity.Property(x => x.ShellVersion).HasMaxLength(32);
            entity.HasOne(x => x.Device).WithOne(d => d.Presence).HasForeignKey<DevicePresenceEntity>(x => x.DeviceId);
        });

        modelBuilder.Entity<DeviceHeartbeatEntity>(entity =>
        {
            entity.HasKey(x => x.Id);
            entity.Property(x => x.DeviceId).HasMaxLength(128);
            entity.Property(x => x.UserName).HasMaxLength(128);
            entity.Property(x => x.OrganizationName).HasMaxLength(256);
            entity.Property(x => x.AgentVersion).HasMaxLength(32);
            entity.Property(x => x.ShellVersion).HasMaxLength(32);
            entity.HasOne(x => x.Device).WithMany(d => d.Heartbeats).HasForeignKey(x => x.DeviceId);
            entity.HasIndex(x => x.DeviceId);
            entity.HasIndex(x => x.ReceivedAtUtc);
        });
    }
}
