using Apollinare.Domain.Entities;
using Microsoft.EntityFrameworkCore;

namespace Apollinare.Infrastructure.Data;

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

    public DbSet<Cliente> Clienti => Set<Cliente>();
    public DbSet<Location> Location => Set<Location>();
    public DbSet<Evento> Eventi => Set<Evento>();
    public DbSet<TipoEvento> TipiEvento => Set<TipoEvento>();
    public DbSet<TipoPasto> TipiPasto => Set<TipoPasto>();
    public DbSet<TipoOspite> TipiOspite => Set<TipoOspite>();
    public DbSet<TipoRisorsa> TipiRisorsa => Set<TipoRisorsa>();
    public DbSet<TipoMateriale> TipiMateriale => Set<TipoMateriale>();
    public DbSet<CodiceCategoria> CodiciCategoria => Set<CodiceCategoria>();
    public DbSet<Risorsa> Risorse => Set<Risorsa>();
    public DbSet<Articolo> Articoli => Set<Articolo>();
    public DbSet<EventoDettaglioOspiti> EventiDettaglioOspiti => Set<EventoDettaglioOspiti>();
    public DbSet<EventoDettaglioPrelievo> EventiDettaglioPrelievo => Set<EventoDettaglioPrelievo>();
    public DbSet<EventoDettaglioRisorsa> EventiDettaglioRisorse => Set<EventoDettaglioRisorsa>();
    public DbSet<EventoAcconto> EventiAcconti => Set<EventoAcconto>();
    public DbSet<EventoAltroCosto> EventiAltriCosti => Set<EventoAltroCosto>();
    public DbSet<EventoAllegato> EventiAllegati => Set<EventoAllegato>();
    public DbSet<EventoDegustazione> EventiDegustazioni => Set<EventoDegustazione>();
    public DbSet<Configurazione> Configurazioni => Set<Configurazione>();
    public DbSet<Utente> Utenti => Set<Utente>();

    // Report entities
    public DbSet<ReportTemplate> ReportTemplates => Set<ReportTemplate>();
    public DbSet<ReportFont> ReportFonts => Set<ReportFont>();
    public DbSet<ReportImage> ReportImages => Set<ReportImage>();
    public DbSet<VirtualDataset> VirtualDatasets => Set<VirtualDataset>();

    // Module system entities
    public DbSet<AppModule> AppModules => Set<AppModule>();
    public DbSet<ModuleSubscription> ModuleSubscriptions => Set<ModuleSubscription>();

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

        // Cliente
        modelBuilder.Entity<Cliente>(entity =>
        {
            entity.HasIndex(e => e.RagioneSociale);
            entity.HasIndex(e => e.PartitaIva);
        });

        // Location
        modelBuilder.Entity<Location>(entity =>
        {
            entity.HasIndex(e => e.Nome);
        });

        // Evento
        modelBuilder.Entity<Evento>(entity =>
        {
            entity.HasIndex(e => e.DataEvento);
            entity.HasIndex(e => e.Stato);
            entity.HasIndex(e => e.Codice);

            entity.HasOne(e => e.Cliente)
                .WithMany(c => c.Eventi)
                .HasForeignKey(e => e.ClienteId)
                .OnDelete(DeleteBehavior.SetNull);

            entity.HasOne(e => e.Location)
                .WithMany(l => l.Eventi)
                .HasForeignKey(e => e.LocationId)
                .OnDelete(DeleteBehavior.SetNull);

            entity.HasOne(e => e.TipoEvento)
                .WithMany(t => t.Eventi)
                .HasForeignKey(e => e.TipoEventoId)
                .OnDelete(DeleteBehavior.SetNull);
        });

        // TipoEvento
        modelBuilder.Entity<TipoEvento>(entity =>
        {
            entity.HasOne(e => e.TipoPasto)
                .WithMany(t => t.TipiEvento)
                .HasForeignKey(e => e.TipoPastoId)
                .OnDelete(DeleteBehavior.SetNull);
        });

        // Articolo
        modelBuilder.Entity<Articolo>(entity =>
        {
            entity.HasIndex(e => e.Codice).IsUnique();

            entity.HasOne(e => e.TipoMateriale)
                .WithMany(t => t.Articoli)
                .HasForeignKey(e => e.TipoMaterialeId)
                .OnDelete(DeleteBehavior.SetNull);

            entity.HasOne(e => e.Categoria)
                .WithMany(c => c.Articoli)
                .HasForeignKey(e => e.CategoriaId)
                .OnDelete(DeleteBehavior.SetNull);
        });

        // Risorsa
        modelBuilder.Entity<Risorsa>(entity =>
        {
            entity.HasOne(e => e.TipoRisorsa)
                .WithMany(t => t.Risorse)
                .HasForeignKey(e => e.TipoRisorsaId)
                .OnDelete(DeleteBehavior.SetNull);
        });

        // EventoDettaglioOspiti
        modelBuilder.Entity<EventoDettaglioOspiti>(entity =>
        {
            entity.HasOne(e => e.Evento)
                .WithMany(ev => ev.DettagliOspiti)
                .HasForeignKey(e => e.EventoId)
                .OnDelete(DeleteBehavior.Cascade);

            entity.HasOne(e => e.TipoOspite)
                .WithMany(t => t.DettagliOspiti)
                .HasForeignKey(e => e.TipoOspiteId)
                .OnDelete(DeleteBehavior.Cascade);
        });

        // EventoDettaglioPrelievo
        modelBuilder.Entity<EventoDettaglioPrelievo>(entity =>
        {
            entity.HasOne(e => e.Evento)
                .WithMany(ev => ev.DettagliPrelievo)
                .HasForeignKey(e => e.EventoId)
                .OnDelete(DeleteBehavior.Cascade);

            entity.HasOne(e => e.Articolo)
                .WithMany(a => a.DettagliPrelievo)
                .HasForeignKey(e => e.ArticoloId)
                .OnDelete(DeleteBehavior.Cascade);
        });

        // EventoDettaglioRisorsa
        modelBuilder.Entity<EventoDettaglioRisorsa>(entity =>
        {
            entity.HasOne(e => e.Evento)
                .WithMany(ev => ev.DettagliRisorse)
                .HasForeignKey(e => e.EventoId)
                .OnDelete(DeleteBehavior.Cascade);

            entity.HasOne(e => e.Risorsa)
                .WithMany(r => r.DettagliRisorse)
                .HasForeignKey(e => e.RisorsaId)
                .OnDelete(DeleteBehavior.Cascade);
        });

        // EventoAcconto
        modelBuilder.Entity<EventoAcconto>(entity =>
        {
            entity.HasOne(e => e.Evento)
                .WithMany(ev => ev.Acconti)
                .HasForeignKey(e => e.EventoId)
                .OnDelete(DeleteBehavior.Cascade);
        });

        // EventoAltroCosto
        modelBuilder.Entity<EventoAltroCosto>(entity =>
        {
            entity.HasOne(e => e.Evento)
                .WithMany(ev => ev.AltriCosti)
                .HasForeignKey(e => e.EventoId)
                .OnDelete(DeleteBehavior.Cascade);
        });

        // EventoAllegato
        modelBuilder.Entity<EventoAllegato>(entity =>
        {
            entity.HasOne(e => e.Evento)
                .WithMany(ev => ev.Allegati)
                .HasForeignKey(e => e.EventoId)
                .OnDelete(DeleteBehavior.Cascade);
        });

        // EventoDegustazione
        modelBuilder.Entity<EventoDegustazione>(entity =>
        {
            entity.HasOne(e => e.Evento)
                .WithMany(ev => ev.Degustazioni)
                .HasForeignKey(e => e.EventoId)
                .OnDelete(DeleteBehavior.Cascade);
        });

        // Configurazione
        modelBuilder.Entity<Configurazione>(entity =>
        {
            entity.HasIndex(e => e.Chiave).IsUnique();
        });

        // Utente
        modelBuilder.Entity<Utente>(entity =>
        {
            entity.HasIndex(e => e.Username).IsUnique();
        });

        // ReportTemplate
        modelBuilder.Entity<ReportTemplate>(entity =>
        {
            entity.HasIndex(e => e.Nome);
            entity.HasIndex(e => e.Categoria);
        });

        // ReportFont
        modelBuilder.Entity<ReportFont>(entity =>
        {
            entity.HasIndex(e => e.FontFamily);
        });

        // ReportImage
        modelBuilder.Entity<ReportImage>(entity =>
        {
            entity.HasIndex(e => e.Categoria);
        });

        // VirtualDataset
        modelBuilder.Entity<VirtualDataset>(entity =>
        {
            entity.HasIndex(e => e.Nome).IsUnique();
            entity.HasIndex(e => e.Categoria);
        });

        // AppModule
        modelBuilder.Entity<AppModule>(entity =>
        {
            entity.HasIndex(e => e.Code).IsUnique();
            entity.HasIndex(e => e.SortOrder);

            entity.Property(e => e.BasePrice)
                .HasPrecision(18, 2);

            entity.Property(e => e.MonthlyMultiplier)
                .HasPrecision(5, 2);
        });

        // ModuleSubscription
        modelBuilder.Entity<ModuleSubscription>(entity =>
        {
            entity.HasIndex(e => e.ModuleId).IsUnique();

            entity.Property(e => e.PaidPrice)
                .HasPrecision(18, 2);

            entity.HasOne(e => e.Module)
                .WithOne(m => m.Subscription)
                .HasForeignKey<ModuleSubscription>(e => e.ModuleId)
                .OnDelete(DeleteBehavior.Cascade);
        });
    }
}
