using Backend.Domain;
using Microsoft.EntityFrameworkCore;

namespace Backend.Data;

public sealed class AwardsDbContext(DbContextOptions<AwardsDbContext> options) : DbContext(options)
{
    public DbSet<Season> Seasons => Set<Season>();
    public DbSet<Category> Categories => Set<Category>();
    public DbSet<Candidate> Candidates => Set<Candidate>();
    public DbSet<StreamerIdentity> StreamerIdentities => Set<StreamerIdentity>();
    public DbSet<AwardResult> Results => Set<AwardResult>();
    public DbSet<ArchivedWinner> ArchivedWinners => Set<ArchivedWinner>();
    public DbSet<Nomination> Nominations => Set<Nomination>();
    public DbSet<VoteBallot> VoteBallots => Set<VoteBallot>();
    public DbSet<VoteEntry> VoteEntries => Set<VoteEntry>();
    public DbSet<UserSession> UserSessions => Set<UserSession>();
    public DbSet<RiskFlag> RiskFlags => Set<RiskFlag>();
    public DbSet<AdminAuditEntry> AdminAuditEntries => Set<AdminAuditEntry>();
    public DbSet<ClipSubmission> ClipSubmissions => Set<ClipSubmission>();
    public DbSet<ShowactApplication> ShowactApplications => Set<ShowactApplication>();
    public DbSet<Sponsor> Sponsors => Set<Sponsor>();
    public DbSet<SiteSettings> SiteSettings => Set<SiteSettings>();
    public DbSet<TeamMember> TeamMembers => Set<TeamMember>();
    public DbSet<TeamRolePermission> TeamRolePermissions => Set<TeamRolePermission>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Season>(entity =>
        {
            entity.HasIndex(item => item.Year).IsUnique();
            entity.Property(item => item.Name).HasMaxLength(160);
            entity.Property(item => item.IsDemo).HasDefaultValue(false);
            entity.Property(item => item.CurrentPhase).HasMaxLength(60);
            entity.Property(item => item.WinnersPublishedByTwitchId).HasMaxLength(120);
            entity.Property(item => item.SubcategoryTemplatesJson).HasDefaultValue("[]");
            entity.Property(item => item.WorkflowRulesJson).HasDefaultValue("[]");
        });

        modelBuilder.Entity<SiteSettings>(entity =>
        {
            entity.Property(item => item.HostDisplayName).HasMaxLength(120);
            entity.Property(item => item.HostTagline).HasMaxLength(160);
            entity.Property(item => item.HostArtistName).HasMaxLength(120);
            entity.Property(item => item.HostImageData).HasColumnType("bytea");
            entity.Property(item => item.HostImageContentType).HasMaxLength(80);
            entity.Property(item => item.NewsletterUrl).HasMaxLength(400);
            entity.Property(item => item.PrivacyEmail).HasMaxLength(160);
            entity.Property(item => item.PrivacyPolicyUpdatedBy).HasMaxLength(120);
            entity.Property(item => item.ImprintUrl).HasMaxLength(400);
            entity.Property(item => item.ContactUrl).HasMaxLength(400);
            entity.Property(item => item.SponsorsUrl).HasMaxLength(400);
            entity.Property(item => item.ShowactsUrl).HasMaxLength(400);
            entity.Property(item => item.ShowactsContent).HasDefaultValue(string.Empty);
            entity.Property(item => item.StreamBannerEyebrow).HasMaxLength(120);
            entity.Property(item => item.StreamBannerTitle).HasMaxLength(160);
            entity.Property(item => item.StreamBannerLiveButtonLabel).HasMaxLength(120);
            entity.Property(item => item.StreamBannerLiveButtonUrl).HasMaxLength(400);
            entity.Property(item => item.StreamBannerLockedButtonLabel).HasMaxLength(120);
            entity.Property(item => item.StreamBannerCompletedEyebrow).HasMaxLength(120);
            entity.Property(item => item.StreamBannerCompletedTitle).HasMaxLength(160);
            entity.Property(item => item.StreamBannerCompletedButtonLabel).HasMaxLength(120);
            entity.Property(item => item.StreamBannerCompletedButtonUrl).HasMaxLength(400);
            entity.Property(item => item.DemoLoginEmail).HasMaxLength(180);
            entity.Property(item => item.DemoLoginPasswordHash).HasMaxLength(120);
            entity.Property(item => item.DemoLoginPasswordSalt).HasMaxLength(80);
            entity.Property(item => item.DemoLoginTwitchUserId).HasMaxLength(120);
            entity.Property(item => item.DemoLoginDisplayName).HasMaxLength(120);
            entity.Property(item => item.TwitchClientId).HasMaxLength(120);
            entity.Property(item => item.TwitchClientSecret).HasMaxLength(180);
            entity.Property(item => item.TwitchRedirectUri).HasMaxLength(400);
            entity.Property(item => item.TwitchScope).HasMaxLength(300);
            entity.Property(item => item.SessionIdleTimeoutHours).HasDefaultValue(3);
            entity.Property(item => item.MaintenanceTitle).HasMaxLength(120);
            entity.Property(item => item.MaintenanceMessage).HasMaxLength(600);
            entity.Property(item => item.WorkflowRulesJson).HasDefaultValue("[]");
            entity.Property(item => item.TrackingRulesJson).HasDefaultValue("[]");
            entity.Property(item => item.ViewerStatsProviderBaseUrl).HasMaxLength(400);
            entity.Property(item => item.NominationLinkBlacklistJson).HasDefaultValue("[]");
            entity.Property(item => item.ClipSubmissionsEnabled).HasDefaultValue(false);
            entity.Property(item => item.ClipReviewEnabled).HasDefaultValue(true);
            entity.Property(item => item.ClipSubmissionDisabledMessage).HasMaxLength(240);
            entity.Property(item => item.ShowactApplicationsEnabled).HasDefaultValue(false);
            entity.Property(item => item.ShowactApplicationStartsAt);
            entity.Property(item => item.ShowactApplicationEndsAt);
            entity.Property(item => item.ShowactApplicationDisabledMessage).HasMaxLength(240);
            entity.Property(item => item.SponsorsVisible).HasDefaultValue(true);
        });

        modelBuilder.Entity<TeamMember>(entity =>
        {
            entity.HasIndex(item => item.Login).IsUnique();
            entity.HasIndex(item => item.BoundTwitchUserId).IsUnique();
            entity.Property(item => item.Login).HasMaxLength(80);
            entity.Property(item => item.DisplayName).HasMaxLength(120);
            entity.Property(item => item.Role).HasMaxLength(40);
            entity.Property(item => item.PasswordHash).HasMaxLength(120);
            entity.Property(item => item.PasswordSalt).HasMaxLength(80);
            entity.Property(item => item.BoundTwitchUserId).HasMaxLength(120);
            entity.Property(item => item.BoundTwitchDisplayName).HasMaxLength(120);
            entity.Property(item => item.CreatedByTwitchId).HasMaxLength(120);
            entity.Property(item => item.UpdatedByTwitchId).HasMaxLength(120);
        });

        modelBuilder.Entity<TeamRolePermission>(entity =>
        {
            entity.HasIndex(item => item.Role).IsUnique();
            entity.Property(item => item.Role).HasMaxLength(40);
            entity.Property(item => item.UpdatedByTwitchId).HasMaxLength(120);
        });

        modelBuilder.Entity<Category>(entity =>
        {
            entity.HasIndex(item => new { item.SeasonId, item.Slug }).IsUnique();
            entity.Property(item => item.GroupName).HasMaxLength(80);
            entity.Property(item => item.Name).HasMaxLength(120);
            entity.Property(item => item.Description).HasMaxLength(400);
            entity.Property(item => item.ViewerRangeMin);
            entity.Property(item => item.ViewerRangeMax);
        });

        modelBuilder.Entity<Candidate>(entity =>
        {
            entity.HasIndex(item => item.StreamerIdentityId);
            entity.Property(item => item.DisplayName).HasMaxLength(120);
            entity.Property(item => item.ChannelSlug).HasMaxLength(120);
            entity.Property(item => item.Platform).HasMaxLength(40);
            entity.Property(item => item.NominationTally).HasDefaultValue(0);
            entity.Property(item => item.AcceptanceStatus).HasMaxLength(30).HasDefaultValue("open");
            entity.Property(item => item.AcceptanceNote).HasMaxLength(500);
            entity.Property(item => item.ClipCompilationUrl).HasMaxLength(500);
            entity.Property(item => item.ClipCompilationTitle).HasMaxLength(200);
            entity.Property(item => item.ClipCompilationPlatform).HasMaxLength(40);
            entity.Property(item => item.ClipEmbedStatus).HasMaxLength(30).HasDefaultValue("unchecked");
        });

        modelBuilder.Entity<StreamerIdentity>(entity =>
        {
            entity.HasIndex(item => item.NormalizedKey).IsUnique();
            entity.Property(item => item.Platform).HasMaxLength(40);
            entity.Property(item => item.Login).HasMaxLength(120);
            entity.Property(item => item.NormalizedKey).HasMaxLength(180);
            entity.Property(item => item.DisplayName).HasMaxLength(120);
            entity.Property(item => item.ProfileUrl).HasMaxLength(500);
        });

        modelBuilder.Entity<Nomination>(entity =>
        {
            entity.Property(item => item.CategoryGroupName).HasMaxLength(80).HasDefaultValue(string.Empty);
            entity.Property(item => item.SubmittedByTwitchId).HasMaxLength(120);
            entity.Property(item => item.CandidateText).HasMaxLength(120);
            entity.Property(item => item.StreamUrl).HasMaxLength(300);
            entity.Property(item => item.ResolvedChannel).HasMaxLength(120);
            entity.Property(item => item.ResolvedPlatform).HasMaxLength(40);
            entity.Property(item => item.HoursStreamed);
            entity.Property(item => item.HoursWatched);
            entity.Property(item => item.PeakViewers);
            entity.Property(item => item.FollowersGained);
            entity.Property(item => item.TrackerStatus).HasMaxLength(40).HasDefaultValue("pending");
            entity.Property(item => item.TrackingReviewStatus).HasMaxLength(30).HasDefaultValue("clear");
            entity.Property(item => item.TrackingFlagsJson).HasDefaultValue("[]");
            entity.Property(item => item.TrackingReviewNote).HasMaxLength(1000);
            entity.Property(item => item.TrackingReviewedByTwitchId).HasMaxLength(120);
            entity.Property(item => item.Status).HasMaxLength(20);
            entity.Property(item => item.ReviewNote).HasMaxLength(500);
            entity.Property(item => item.ReviewedByTwitchId).HasMaxLength(120);
            entity.HasIndex(item => new { item.SeasonId, item.Status });
            entity.HasIndex(item => new { item.SeasonId, item.CategoryGroupName, item.Status });
            entity.HasIndex(item => new { item.SeasonId, item.StreamerIdentityId, item.CategoryGroupName });
            entity.HasOne(item => item.Category)
                .WithMany()
                .HasForeignKey(item => item.CategoryId)
                .OnDelete(DeleteBehavior.SetNull);
            entity.HasOne(item => item.SuggestedCategory)
                .WithMany()
                .HasForeignKey(item => item.SuggestedCategoryId)
                .OnDelete(DeleteBehavior.SetNull);
        });

        modelBuilder.Entity<VoteBallot>(entity =>
        {
            entity.HasIndex(item => new { item.SeasonId, item.SubmittedByTwitchId }).IsUnique();
            entity.Property(item => item.SubmittedByTwitchId).HasMaxLength(120);
            entity.Property(item => item.Status).HasMaxLength(30);
        });

        modelBuilder.Entity<AwardResult>(entity =>
        {
            entity.HasIndex(item => new { item.SeasonId, item.CategoryId }).IsUnique();
            entity.Property(item => item.CategoryName).HasMaxLength(120);
        });

        modelBuilder.Entity<ArchivedWinner>(entity =>
        {
            entity.HasIndex(item => new { item.Year, item.Category, item.Subcategory }).IsUnique();
            entity.Property(item => item.Category).HasMaxLength(120);
            entity.Property(item => item.Subcategory).HasMaxLength(120);
            entity.Property(item => item.WinnerName).HasMaxLength(120);
            entity.Property(item => item.WinnerUrl).HasMaxLength(500);
        });

        modelBuilder.Entity<UserSession>(entity =>
        {
            entity.HasIndex(item => item.SessionToken).IsUnique();
            entity.Property(item => item.SessionToken).HasMaxLength(120);
            entity.Property(item => item.TwitchUserId).HasMaxLength(120);
            entity.Property(item => item.DisplayName).HasMaxLength(120);
            entity.Property(item => item.Role).HasMaxLength(40);
            entity.Property(item => item.CreatedFromIp).HasMaxLength(80);
            entity.Property(item => item.UserAgent).HasMaxLength(400);
        });

        modelBuilder.Entity<RiskFlag>(entity =>
        {
            entity.Property(item => item.TwitchUserId).HasMaxLength(120);
            entity.Property(item => item.Source).HasMaxLength(80);
            entity.Property(item => item.Type).HasMaxLength(80);
            entity.Property(item => item.Severity).HasMaxLength(20);
            entity.Property(item => item.Status).HasMaxLength(20);
            entity.Property(item => item.Summary).HasMaxLength(240);
            entity.Property(item => item.CreatedFromIp).HasMaxLength(80);
            entity.Property(item => item.UserAgent).HasMaxLength(400);
            entity.Property(item => item.ReviewNote).HasMaxLength(500);
            entity.Property(item => item.ReviewedByTwitchId).HasMaxLength(120);
        });

        modelBuilder.Entity<AdminAuditEntry>(entity =>
        {
            entity.Property(item => item.AdminTwitchUserId).HasMaxLength(120);
            entity.Property(item => item.ActionType).HasMaxLength(80);
            entity.Property(item => item.EntityType).HasMaxLength(80);
            entity.Property(item => item.EntityId).HasMaxLength(120);
            entity.Property(item => item.Summary).HasMaxLength(240);
            entity.Property(item => item.CreatedFromIp).HasMaxLength(80);
            entity.Property(item => item.UserAgent).HasMaxLength(400);
        });

        modelBuilder.Entity<ClipSubmission>(entity =>
        {
            entity.Property(item => item.SubmittedByTwitchId).HasMaxLength(120);
            entity.Property(item => item.ClipUrl).HasMaxLength(500);
            entity.Property(item => item.Title).HasMaxLength(200);
            entity.Property(item => item.Creator).HasMaxLength(120);
            entity.Property(item => item.Platform).HasMaxLength(40);
            entity.Property(item => item.Status).HasMaxLength(20);
            entity.Property(item => item.ReviewNote).HasMaxLength(500);
            entity.Property(item => item.ReviewedByTwitchId).HasMaxLength(120);
            entity.Property(item => item.CreatedFromIp).HasMaxLength(80);
            entity.HasIndex(item => new { item.SeasonId, item.Status });
            entity.HasIndex(item => item.CandidateId);
            entity.HasOne<Season>()
                .WithMany()
                .HasForeignKey(item => item.SeasonId)
                .OnDelete(DeleteBehavior.Cascade);
            entity.HasOne(item => item.Candidate)
                .WithMany()
                .HasForeignKey(item => item.CandidateId)
                .OnDelete(DeleteBehavior.SetNull);
        });

        modelBuilder.Entity<ShowactApplication>(entity =>
        {
            entity.Property(item => item.ArtistName).HasMaxLength(120);
            entity.Property(item => item.ContactEmail).HasMaxLength(180);
            entity.Property(item => item.ContactDiscord).HasMaxLength(120);
            entity.Property(item => item.PlatformUrl).HasMaxLength(500);
            entity.Property(item => item.PerformanceType).HasMaxLength(80);
            entity.Property(item => item.Description).HasMaxLength(1000);
            entity.Property(item => item.TechnicalNotes).HasMaxLength(1000);
            entity.Property(item => item.ReferenceUrl).HasMaxLength(500);
            entity.Property(item => item.Status).HasMaxLength(20);
            entity.Property(item => item.ReviewNote).HasMaxLength(500);
            entity.Property(item => item.ReviewedByTwitchId).HasMaxLength(120);
            entity.Property(item => item.CreatedFromIp).HasMaxLength(80);
            entity.Property(item => item.UserAgent).HasMaxLength(400);
            entity.HasIndex(item => new { item.SeasonId, item.Status });
        });

        modelBuilder.Entity<Sponsor>(entity =>
        {
            entity.Property(item => item.Name).HasMaxLength(120);
            entity.Property(item => item.WebsiteUrl).HasMaxLength(500);
            entity.Property(item => item.LogoUrl).HasMaxLength(500);
            entity.Property(item => item.Description).HasMaxLength(500);
            entity.Property(item => item.Tier).HasMaxLength(80);
            entity.HasIndex(item => new { item.SeasonId, item.IsVisible, item.SortOrder });
        });
    }
}
