using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using NexusReader.Domain.Entities;

namespace NexusReader.Data.Persistence;

public class AppDbContext : IdentityDbContext<NexusUser>
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
    {
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
        // Suppress the pending model changes warning to avoid runtime exceptions in some environments
        optionsBuilder.ConfigureWarnings(w => w.Ignore(Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.PendingModelChangesWarning));
    }

    public DbSet<SemanticKnowledgeCache> SemanticKnowledgeCache => Set<SemanticKnowledgeCache>();
    public DbSet<KnowledgeUnit> KnowledgeUnits => Set<KnowledgeUnit>();
    public DbSet<KnowledgeUnitLink> KnowledgeUnitLinks => Set<KnowledgeUnitLink>();
    public DbSet<Ebook> Ebooks => Set<Ebook>();
    public DbSet<QuizResult> QuizResults => Set<QuizResult>();
    public DbSet<SubscriptionPlan> SubscriptionPlans => Set<SubscriptionPlan>();
    public DbSet<Author> Authors => Set<Author>();

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

        modelBuilder.Entity<NexusUser>(entity =>
        {
            entity.Property(u => u.LastReadPageId).HasMaxLength(255);
            entity.Property(u => u.LastReadAt).IsRequired(false);
            entity.HasIndex(u => u.TenantId);

            entity.HasOne(u => u.SubscriptionPlan)
                .WithMany()
                .HasForeignKey(u => u.SubscriptionPlanId)
                .OnDelete(DeleteBehavior.Restrict);
            
            // Note: DefaultValue for int is 1 (which corresponds to 'Free' in our seed)
            entity.Property(u => u.SubscriptionPlanId)
                .HasDefaultValue(1);
        });

        modelBuilder.Entity<SubscriptionPlan>(entity =>
        {
            entity.HasIndex(p => p.PlanName).IsUnique();
        });

        modelBuilder.Entity<SemanticKnowledgeCache>(entity =>
        {
            entity.HasKey(e => e.ContentHash);
            entity.HasIndex(e => e.ContentHash).IsUnique();
            entity.HasIndex(e => e.TenantId);
            entity.Ignore(e => e.Embedding);
        });

        modelBuilder.Entity<KnowledgeUnit>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.HasIndex(e => e.TenantId);
            entity.HasIndex(e => e.EbookId);

            entity.HasOne(e => e.Ebook)
                .WithMany()
                .HasForeignKey(e => e.EbookId)
                .OnDelete(DeleteBehavior.Cascade);
        });

        modelBuilder.Entity<KnowledgeUnitLink>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.HasOne(e => e.SourceUnit)
                .WithMany(u => u.OutgoingLinks)
                .HasForeignKey(e => e.SourceUnitId)
                .OnDelete(DeleteBehavior.Cascade);

            entity.HasOne(e => e.TargetUnit)
                .WithMany(u => u.IncomingLinks)
                .HasForeignKey(e => e.TargetUnitId)
                .OnDelete(DeleteBehavior.Cascade);
        });

        modelBuilder.Entity<Ebook>(entity =>
        {
            entity.HasOne(e => e.User)
                .WithMany(u => u.Ebooks)
                .HasForeignKey(e => e.UserId)
                .OnDelete(DeleteBehavior.Cascade);

            entity.HasOne(e => e.Author)
                .WithMany(a => a.Ebooks)
                .HasForeignKey(e => e.AuthorId)
                .OnDelete(DeleteBehavior.Restrict);
            
            entity.HasIndex(e => e.TenantId);
        });

        modelBuilder.Entity<QuizResult>(entity =>
        {
            entity.HasOne(e => e.User)
                .WithMany(u => u.QuizResults)
                .HasForeignKey(e => e.UserId)
                .OnDelete(DeleteBehavior.Cascade);
            
            entity.HasIndex(e => e.TenantId);
        });

        // Seed Subscription Plans with deterministic IDs
        modelBuilder.Entity<SubscriptionPlan>().HasData(
            new SubscriptionPlan { Id = 1, PlanName = SubscriptionPlan.FreeName, AITokenLimit = 5000, IsUnlimitedTokens = false, MonthlyPrice = 0m, StripeProductId = "prod_Free789" },
            new SubscriptionPlan { Id = 2, PlanName = SubscriptionPlan.BasicName, AITokenLimit = 10000, IsUnlimitedTokens = false, MonthlyPrice = 9.99m, StripeProductId = "prod_basic_placeholder" },
            new SubscriptionPlan { Id = 3, PlanName = SubscriptionPlan.ProName, AITokenLimit = 50000, IsUnlimitedTokens = false, MonthlyPrice = 19.99m, StripeProductId = "prod_pro_placeholder" },
            new SubscriptionPlan { Id = 4, PlanName = SubscriptionPlan.EnterpriseName, AITokenLimit = 1000000000, IsUnlimitedTokens = true, MonthlyPrice = 99.99m, StripeProductId = "prod_enterprise_placeholder" }
        );
    }
}
