using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace qdr.app.bundleboiler.data.Model
{
    public class BoilerDbContext : DbContext
    {
        public BoilerDbContext(DbContextOptions<BoilerDbContext> options) : base(options)
        {
        }

        public DbSet<Activity> Activities { get; set; }
        public DbSet<Artifact> Artifacts { get; set; }
        public DbSet<ArtifactAttribute> ArtifactAttributes { get; set; }
        public DbSet<Attachment> Attachments { get; set; }
        public DbSet<AttributeCategory> AttributeCategories { get; set; }
        public DbSet<Bundle> Bundles { get; set; }
        public DbSet<BundleAttribute> BundleAttributes { get; set; }
        public DbSet<Enumeration> Enumerations { get; set; }
        public DbSet<Project> Projects { get; set; }
        public DbSet<Realization> Realizations { get; set; }

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

            modelBuilder.Entity<Activity>(BuildActivity);
            modelBuilder.Entity<Artifact>(BuildArtifact);
            modelBuilder.Entity<ArtifactAttribute>(BuildArtifactAttribute);
            modelBuilder.Entity<Attachment>(BuildAttachment);
            modelBuilder.Entity<AttributeCategory>(BuildAttributeCategory);
            modelBuilder.Entity<Bundle>(BuildBundle);
            modelBuilder.Entity<BundleAttribute>(BuildBundleAttribute);
            modelBuilder.Entity<Enumeration>(BuildEnumeration);
            modelBuilder.Entity<Project>(BuildProject);
            modelBuilder.Entity<Realization>(BuildRealization);
        }

        private void BuildActivity(EntityTypeBuilder<Activity> builder)
        {
            builder.HasKey(x => x.Id);
            builder.Property(x => x.Code).IsRequired().HasMaxLength(50);
            builder.Property(x => x.Name).IsRequired().HasMaxLength(250);
            builder.Property(x => x.Description).HasMaxLength(500);
            builder.Property(x => x.ClassType).IsRequired();
            builder.HasOne(x => x.Parent)
                   .WithMany(x => x.Activities)
                   .IsRequired();
        }

        private void BuildArtifact(EntityTypeBuilder<Artifact> builder)
        {
            builder.HasKey(x => x.Id);
            builder.Property(x => x.VersionCode).IsRequired().HasMaxLength(20);
            builder.Property(x => x.Description).HasMaxLength(500);
            builder.Property(x => x.OrderNo).IsRequired();
            builder.HasOne(x => x.Type).WithMany().IsRequired();
            builder.HasOne(x => x.Parent)
                   .WithMany(x => x.Artifacts)
                   .IsRequired();
            builder.HasMany(x => x.Attributes)
                   .WithOne(x => x.Owner)
                   .IsRequired();
        }

        private void BuildArtifactAttribute(EntityTypeBuilder<ArtifactAttribute> builder)
        {
            builder.HasKey(x => x.Id);
            builder.HasOne(x => x.Parent)
                   .WithMany()
                   .IsRequired();
            builder.HasOne(x => x.Owner)
                   .WithMany(x => x.Attributes)
                   .IsRequired();
        }

        private void BuildAttachment(EntityTypeBuilder<Attachment> builder)
        {
            builder.HasKey(x => x.Id);
            builder.Property(x => x.FileName).IsRequired().HasMaxLength(250);
            builder.Property(x => x.ContentType).IsRequired().HasMaxLength(50);
            builder.Property(x => x.Content).IsRequired();
            builder.HasOne(x => x.Parent)
                   .WithMany(x => x.Attachments)
                   .IsRequired();
        }

        private void BuildAttributeCategory(EntityTypeBuilder<AttributeCategory> builder)
        {
            builder.HasKey(x => x.Id);
            builder.Property(x => x.Code).IsRequired().HasMaxLength(50);
            builder.Property(x => x.Name).IsRequired().HasMaxLength(250);
            builder.Property(x => x.Description).HasMaxLength(500);
            builder.Property(x => x.DefaultValue).HasMaxLength(500);
            builder.Property(x => x.ClassType).IsRequired();
        }

        private void BuildBundle(EntityTypeBuilder<Bundle> builder)
        {
            builder.HasKey(x => x.Id);
            builder.Property(x => x.Code).IsRequired().HasMaxLength(50);
            builder.Property(x => x.Name).IsRequired().HasMaxLength(250);
            builder.Property(x => x.Description).HasMaxLength(500);
            builder.Property(x => x.VersionMajor).IsRequired();
            builder.Property(x => x.VersionMinor).IsRequired();
            builder.Property(x => x.VersionRevision).IsRequired();
            
            builder.HasOne(x => x.BundleType)
                   .WithMany()
                   .IsRequired();
            
            builder.HasMany(x => x.Artifacts)
                   .WithOne(x => x.Parent)
                   .IsRequired();
            
            builder.HasMany(x => x.Attributes)
                   .WithOne(x => x.Owner)
                   .IsRequired();
            
            builder.HasMany(x => x.Realizations)
                   .WithOne(x => x.Parent)
                   .IsRequired();
            
            builder.HasMany(x => x.Environments)
                   .WithMany();
            
            builder.HasMany(x => x.Forks)
                   .WithMany();
            
            builder.HasOne(x => x.Follows)
                   .WithMany(x => x.Covers)
                   .IsRequired(false);
        }

        private void BuildBundleAttribute(EntityTypeBuilder<BundleAttribute> builder)
        {
            builder.HasKey(x => x.Id);
            builder.HasOne(x => x.Parent)
                   .WithMany()
                   .IsRequired();
            builder.HasOne(x => x.Owner)
                   .WithMany(x => x.Attributes)
                   .IsRequired();
        }

        private void BuildEnumeration(EntityTypeBuilder<Enumeration> builder)
        {
            builder.HasKey(x => x.Id);
            builder.Property(x => x.Code).IsRequired().HasMaxLength(50);
            builder.Property(x => x.Name).IsRequired().HasMaxLength(250);
            builder.Property(x => x.Description).HasMaxLength(500);
            builder.Property(x => x.ClassType).IsRequired();
            builder.Property(x => x.OrderNo).IsRequired();
        }

        private void BuildProject(EntityTypeBuilder<Project> builder)
        {
            builder.HasKey(x => x.Id);
            builder.Property(x => x.Code).IsRequired().HasMaxLength(50);
            builder.Property(x => x.Name).IsRequired().HasMaxLength(250);
            builder.Property(x => x.Description).HasMaxLength(500);
            builder.HasMany(x => x.Activities)
                   .WithOne(x => x.Parent)
                   .IsRequired();
        }

        private void BuildRealization(EntityTypeBuilder<Realization> builder)
        {
            builder.HasKey(x => x.Id);
            builder.Property(x => x.Merged).IsRequired();
            builder.Property(x => x.MergedToLinkSCM).HasMaxLength(500);
            
            builder.HasOne(x => x.Parent)
                   .WithMany(x => x.Realizations)
                   .IsRequired();
            
            builder.HasMany(x => x.Attachments)
                   .WithOne(x => x.Parent)
                   .IsRequired();
            
            builder.HasMany(x => x.Forks)
                   .WithMany();
            
            builder.HasMany(x => x.Environments)
                   .WithMany();
            
            builder.HasOne(x => x.BundleType)
                   .WithMany()
                   .IsRequired();
        }
    }
}