using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using AyaNova.Util;
using Microsoft.Extensions.Logging;

namespace AyaNova.Models
{
    public partial class AyContext : DbContext
    {
        public virtual DbSet<Event> Event { get; set; }
        public virtual DbSet<SearchDictionary> SearchDictionary { get; set; }
        public virtual DbSet<SearchKey> SearchKey { get; set; }
        public virtual DbSet<User> User { get; set; }
        public virtual DbSet<UserOptions> UserOptions { get; set; }
        public virtual DbSet<License> License { get; set; }
        public virtual DbSet<Widget> Widget { get; set; }
        public virtual DbSet<FileAttachment> FileAttachment { get; set; }
        public virtual DbSet<OpsJob> OpsJob { get; set; }
        public virtual DbSet<OpsJobLog> OpsJobLog { get; set; }
        public virtual DbSet<Locale> Locale { get; set; }
        public virtual DbSet<LocaleItem> LocaleItem { get; set; }
        public virtual DbSet<DataFilter> DataFilter { get; set; }
        public virtual DbSet<Tag> Tag { get; set; }
        public virtual DbSet<FormCustom> FormCustom { get; set; }

        //Note: had to add this constructor to work with the code in startup.cs that gets the connection string from the appsettings.json file
        //and commented out the above on configuring
        public AyContext(DbContextOptions<AyContext> options) : base(options)
        { }



        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {

            //AUTOMATICALLY MATCH NAMES
            //https://andrewlock.net/customising-asp-net-core-identity-ef-core-naming-conventions-for-postgresql/
            foreach (var entity in modelBuilder.Model.GetEntityTypes())
            {
                // Replace table names
                //entity.Relational().TableName = "a" + entity.Relational().TableName.ToLowerInvariant();
                entity.SetTableName("a" + entity.GetTableName().ToLowerInvariant());

                // Replace column names            
                foreach (var property in entity.GetProperties())
                {
                    //Any object that has a concurrencytoken field
                    //set it up to work properly with PostgreSQL
                    if (property.Name == "ConcurrencyToken")
                    {
                        property.SetColumnName("xmin");
                        property.SetColumnType("xid");
                        // property.Relational().ColumnName = "xmin";
                        // property.Relational().ColumnType = "xid";
                        property.ValueGenerated = ValueGenerated.OnAddOrUpdate;
                        property.IsConcurrencyToken = true;
                    }
                    else
                        property.SetColumnName(property.Name.ToLowerInvariant());
                }

                foreach (var key in entity.GetKeys())
                {
                    key.SetName(key.GetName().ToLowerInvariant());
                    // key.Relational().Name = key.Relational().Name.ToLowerInvariant();
                }

                foreach (var key in entity.GetForeignKeys())
                {
                    //key.Relational().Name = key.Relational().Name.ToLowerInvariant();

                    key.SetConstraintName(key.GetConstraintName().ToLowerInvariant());
                }

                foreach (var index in entity.GetIndexes())
                {
                    index.SetName(index.GetName().ToLowerInvariant());
                    //index.Relational().Name = index.Relational().Name.ToLowerInvariant();
                }
            }

            //Indexes must be specified through fluent api unfortunately
            modelBuilder.Entity<FileAttachment>().HasIndex(p => p.StoredFileName);

            //Relationships
            modelBuilder.Entity<Locale>()
                .HasMany(c => c.LocaleItems)
                .WithOne(e => e.Locale)
                .IsRequired();//default delete behaviour is cascade when set to isrequired

            modelBuilder.Entity<User>()
                       .HasOne(p => p.UserOptions)
                       .WithOne(i => i.User)
                       .HasForeignKey<UserOptions>(b => b.UserId)
                       .OnDelete(DeleteBehavior.Cascade);//Hopefully will delete the useroptions with the user?

            //User->Widget  this might be wrong
            modelBuilder.Entity<User>()
                      .HasOne(p => p.Widget)
                      .WithOne(i => i.User)
                      .HasForeignKey<Widget>(b => b.UserId)
                      .OnDelete(DeleteBehavior.NoAction);




            //-----------
        }

    }

}