using Microsoft.EntityFrameworkCore;

namespace MangaReader.Core.Data;

public class MangaContext(DbContextOptions options) : DbContext(options)
{
    public DbSet<Manga> Mangas { get; set; }
    public DbSet<MangaCover> MangaCovers { get; set; }
    public DbSet<MangaTitle> MangaTitles { get; set; }
    public DbSet<Source> Sources { get; set; }
    public DbSet<MangaSource> MangaSources { get; set; }
    public DbSet<Contributor> Contributors { get; set; }
    public DbSet<MangaContributor> MangaContributors { get; set; }
    public DbSet<Genre> Genres { get; set; }
    public DbSet<MangaGenre> MangaGenres { get; set; }
    public DbSet<MangaChapter> MangaChapters { get; set; }
    public DbSet<ChapterSource> ChapterSources { get; set; }
    public DbSet<ChapterPage> ChapterPages { get; set; }

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

        ConfigureManga(modelBuilder);
        ConfigureMangaCover(modelBuilder);
        ConfigureMangaTitle(modelBuilder);
        ConfigureSource(modelBuilder);
        ConfigureMangaSource(modelBuilder);
        ConfigureContributor(modelBuilder);
        ConfigureMangaContributor(modelBuilder);
        ConfigureGenre(modelBuilder);
        ConfigureMangaGenre(modelBuilder);
        ConfigureMangaChapter(modelBuilder);
        ConfigureChapterSource(modelBuilder);
        ConfigureChapterPage(modelBuilder);
    }

    private static void ConfigureManga(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity<Manga>()
            .HasKey(x => x.MangaId);

        modelBuilder.Entity<Manga>()
            .HasIndex(x => x.Title)
            .IsUnique();

        modelBuilder.Entity<Manga>()
            .HasIndex(x => x.Slug)
            .IsUnique();
    }

    private static void ConfigureMangaCover(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity<MangaCover>()
            .HasKey(x => x.MangaCoverId);

        modelBuilder
            .Entity<MangaCover>()
            .HasOne(x => x.Manga)
            .WithMany(x => x.Covers)
            .HasForeignKey(x => x.MangaId)
            .OnDelete(DeleteBehavior.Cascade);

        modelBuilder.Entity<MangaCover>()
            .HasIndex(x => x.Guid)
            .IsUnique();

        //modelBuilder
        //    .Entity<MangaCover>()
        //    .HasIndex(x => new { x.MangaId, x.IsPrimary })
        //    .IsUnique()
        //    .HasFilter("[IsPrimary] = 1"); // Enforce only one primary cover per manga
    }

    private static void ConfigureMangaTitle(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity<MangaTitle>()
            .HasKey(mangaTitle => mangaTitle.MangaTitleId);

        modelBuilder.Entity<MangaTitle>()
            .HasIndex(mangaTitle => new { mangaTitle.MangaId, mangaTitle.Name })
            .IsUnique();

        modelBuilder
            .Entity<MangaTitle>()
            .HasIndex(mangaTitle => mangaTitle.Name);

        modelBuilder
            .Entity<MangaTitle>()
            .HasOne(x => x.Manga)
            .WithMany(x => x.Titles)
            .HasForeignKey(x => x.MangaId)
            .OnDelete(DeleteBehavior.Cascade);
    }

    private static void ConfigureSource(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity<Source>()
            .HasKey(x => x.SourceId);

        modelBuilder
            .Entity<Source>()
            .HasIndex(x => x.Name)
            .IsUnique(true);
    }

    private static void ConfigureMangaSource(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity<MangaSource>()
            .HasKey(mangaSource => new { mangaSource.MangaId, mangaSource.SourceId });

        modelBuilder.Entity<MangaSource>()
            .HasIndex(x => x.Url)
            .IsUnique();

        modelBuilder
            .Entity<MangaSource>()
            .HasOne(x => x.Manga)
            .WithMany(x => x.Sources)
            .HasForeignKey(x => x.MangaId)
            .OnDelete(DeleteBehavior.Cascade);
    }

    private static void ConfigureContributor(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity<Contributor>()
            .HasKey(x => x.ContributorId);

        modelBuilder
            .Entity<Contributor>()
            .HasIndex(x => x.Name)
            .IsUnique(true);
    }

    private static void ConfigureMangaContributor(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity<MangaContributor>()
            .HasKey(mc => new { mc.MangaId, mc.ContributorId, mc.Role });

        modelBuilder
            .Entity<MangaContributor>()
            .HasOne(x => x.Manga)
            .WithMany(x => x.Contributors)
            .HasForeignKey(x => x.MangaId)
            .OnDelete(DeleteBehavior.Cascade);
    }

    private static void ConfigureGenre(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity<Genre>()
            .HasKey(x => x.GenreId);

        modelBuilder
            .Entity<Genre>()
            .HasIndex(x => x.Name)
            .IsUnique(true);
    }

    private static void ConfigureMangaGenre(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity<MangaGenre>()
            .HasKey(mangaGenre => new { mangaGenre.MangaId, mangaGenre.GenreId });

        modelBuilder
            .Entity<MangaGenre>()
            .HasOne(x => x.Manga)
            .WithMany(x => x.Genres)
            .HasForeignKey(x => x.MangaId)
            .OnDelete(DeleteBehavior.Cascade);
    }

    private static void ConfigureMangaChapter(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity<MangaChapter>()
            .HasKey(x => x.MangaChapterId);

        modelBuilder
            .Entity<MangaChapter>()
            .HasOne(x => x.Manga)
            .WithMany(x => x.Chapters)
            .HasForeignKey(x => x.MangaId)
            .OnDelete(DeleteBehavior.Cascade);
    }

    private static void ConfigureChapterSource(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity<ChapterSource>()
            .HasKey(chapterSource => new { chapterSource.MangaChapterId, chapterSource.SourceId });

        modelBuilder
            .Entity<ChapterSource>()
            .HasOne(x => x.Chapter)
            .WithMany(x => x.Sources)
            .HasForeignKey(x => x.MangaChapterId)
            .OnDelete(DeleteBehavior.Cascade);
    }

    private static void ConfigureChapterPage(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity<ChapterPage>()
            .HasKey(chapterPage => chapterPage.ChapterPageId);

        modelBuilder
            .Entity<ChapterPage>()
            .HasIndex(chapterPage => new { chapterPage.MangaChapterId, chapterPage.PageNumber })
            .IsUnique(true);

        modelBuilder
            .Entity<ChapterPage>()
            .HasOne(x => x.MangaChapter)
            .WithMany(x => x.Pages)
            .HasForeignKey(x => x.MangaChapterId)
            .OnDelete(DeleteBehavior.Cascade);
    }
}