using DAL._Shared.SharedModels;
using DAL.Models.Entities;
using HRD.WebApi.DAL;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Linq;

namespace DAL
{
    public partial class WebApiContext : WebApiBaseContext
    {
        private readonly WebApiContextOptions _options;

        private readonly ILogger<WebApiContext> _logger;

        public WebApiContext(DbContextOptions<WebApiContext> options, IOptions<WebApiContextOptions> webApiContextOptions, ILogger<WebApiContext> logger) : base(options)
        {
            _options = webApiContextOptions.Value;
            _logger = logger;
        }

        public virtual DbSet<WebAppUser> WebAppUserSet { get; set; }
        public virtual DbSet<WebAppEmployeeInfo> WebAppEmployeeInfo { get; set; }

        public virtual DbSet<AdWebAppToWebAppRole> AdWebAppToWebAppRoleSet { get; set; }
        public virtual DbSet<CostCentre> CostCentreSet { get; set; }
        public virtual DbSet<Department> DepartmentSet { get; set; }
        public virtual DbSet<DocumentArt> DocumentArtSet { get; set; }
        public virtual DbSet<EmployeeAttribute> EmployeeAttributeSet { get; set; }
        public virtual DbSet<EmployeeStatus> EmployeeStatusSet { get; set; }
        public virtual DbSet<Project> ProjectSet { get; set; }
        public virtual DbSet<Rang> RangSet { get; set; }
        public virtual DbSet<WebApp> WebAppSet { get; set; }
        public virtual DbSet<WebAppRole> WebAppRoleSet { get; set; }
        public virtual DbSet<DepartmentToWebAppToEmployeeForWindream> DepartmentToWebAppToEmployeeForWindreamSet { get; set; }
        public virtual DbSet<DocumentArtToDepartment> DocumentArtToDepartmentSet { get; set; }
        public virtual DbSet<Employee> EmployeeSet { get; set; }
        public virtual DbSet<EmployeeToAttribute> EmployeeToAttributeSet { get; set; }
        public virtual DbSet<EmployeeToDepartment> EmployeeToDepartmentSet { get; set; }
        public virtual DbSet<EmployeeToWebApp> EmployeeToWebAppSet { get; set; }
        public virtual DbSet<WebAppAdditionalRole> WebAppAdditionalRoleSet { get; set; }
        public virtual DbSet<WebAppToDepartment> WebAppToDepartmentSet { get; set; }
        public virtual DbSet<WebAppToWebAppAdditionalRole> WebAppToWebAppAdditionalRoleSet { get; set; }
        public virtual DbSet<WebAppToWebAppRole> WebAppToWebAppRoleSet { get; set; }
        public virtual DbSet<WindreamColumnsToDepartment> WindreamColumnsToDepartmentSet { get; set; }
        public virtual DbSet<WindreamIndex> WindreamIndexSet { get; set; }
        public virtual DbSet<WindreamIndexToWindreamSearchToDepartment> WindreamIndexToWindreamSearchToDepartmentSet { get; set; }
        public virtual DbSet<WindreamSearch> WindreamSearchSet { get; set; }
        public virtual DbSet<WindreamSearchItem> WindreamSearchItemSet { get; set; }
        public virtual DbSet<WindreamSearchItemToWindreamSearchToDepartment> WindreamSearchItemToWindreamSearchToDepartmentSet { get; set; }
        public virtual DbSet<WindreamSearchToDepartment> WindreamSearchToDepartmentSet { get; set; }
        public virtual DbSet<WindreamInputFolder> WindreamInputFolderSet { get; set; }
        public virtual DbSet<Subsidiary> SubsidiarySet { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            switch(_options.TableNamingRule)
            {
                case "DIGITAL_DATA":
                    OnModelCreating_DDSQLNaming(modelBuilder);
                    break;
                case "PREPARED-SQL":
                    OnModelCreating_PreparedSQL(modelBuilder);
                    break;
                default:
                    _logger.LogWarning($"The WebApiContextOptions.TableNamingRule is set to {_options?.TableNamingRule ?? "NULL"}  in appsettings.json. Hence, it has been defaulted to PREPARED-SQL.");
                    OnModelCreating_PreparedSQL(modelBuilder);
                    break;
            }     

            base.OnModelCreating(modelBuilder);
        }

        protected static void OnModelCreating_PreparedSQL(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Subsidiary>(entity =>
            {
                entity.ToTable("Subsidiary", "dbo");
            });

            modelBuilder.Entity<WindreamInputFolder>(entity =>
            {
                entity.ToTable("WindreamInputFolder", "ecm");
            });

            modelBuilder.Entity<WindreamSearchToDepartment>(entity =>
            {
                entity.ToTable("WindreamSearchToDepartment", "ecm");
            });

            modelBuilder.Entity<WindreamSearchItemToWindreamSearchToDepartment>(entity =>
            {
                entity.ToTable("WindreamSearchItemToWindreamSearchToDepartment", "ecm");
            });

            modelBuilder.Entity<WindreamSearchItem>(entity =>
            {
                entity.ToTable("WindreamSearchItem", "ecm");
            });

            modelBuilder.Entity<WindreamSearch>(entity =>
            {
                entity.ToTable("WindreamSearch", "ecm");
            });

            modelBuilder.Entity<WindreamIndexToWindreamSearchToDepartment>(entity =>
            {
                entity.ToTable("WindreamIndexToWindreamSearchToDepartment", "ecm");
            });

            modelBuilder.Entity<WindreamIndex>(entity =>
            {
                entity.ToTable("WindreamIndex", "ecm");
            });

            // 'WindreamColumnsToDepartment' tablosu güncellenmiş listeye dahil değil

            modelBuilder.Entity<WebAppToWebAppRole>(entity =>
            {
                entity.ToTable("WebAppToWebAppRole", "dbo");
            });

            modelBuilder.Entity<WebAppToWebAppAdditionalRole>(entity =>
            {
                entity.ToTable("WebAppToWebAppAdditionalRole", "dbo");
            });

            modelBuilder.Entity<WebAppToDepartment>(entity =>
            {
                entity.ToTable("WebAppToDepartment", "dbo");
            });

            modelBuilder.Entity<WebAppAdditionalRole>(entity =>
            {
                entity.ToTable("WebAppAdditionalRole", "dbo");
            });

            modelBuilder.Entity<EmployeeToWebApp>(entity =>
            {
                entity.ToTable("EmployeeToWebApp", "hr");
            });

            modelBuilder.Entity<EmployeeToDepartment>(entity =>
            {
                entity.ToTable("EmployeeToDepartment", "hr");
            });

            modelBuilder.Entity<EmployeeToAttribute>(entity =>
            {
                entity.ToTable("EmployeeToAttribute", "hr");
            });

            modelBuilder.Entity<Employee>(entity =>
            {
                entity.ToTable("Employee", "hr");
            });

            modelBuilder.Entity<DocumentArtToDepartment>(entity =>
            {
                entity.ToTable("DocumentArtToDepartment", "ecm");
            });

            // 'DepartmentToWebAppToEmployeeForWindream' tablosu güncellenmiş listeye dahil değil

            modelBuilder.Entity<WebAppRole>(entity =>
            {
                entity.ToTable("WebAppRole", "dbo");
            });

            modelBuilder.Entity<WebApp>(entity =>
            {
                entity.ToTable("WebApp", "dbo");
            });

            modelBuilder.Entity<Rang>(entity =>
            {
                entity.ToTable("Rang", "hr");
            });

            modelBuilder.Entity<Project>(entity =>
            {
                entity.ToTable("Project", "hr");
            });

            modelBuilder.Entity<EmployeeStatus>(entity =>
            {
                entity.ToTable("EmployeeStatus", "hr");
            });

            modelBuilder.Entity<EmployeeAttribute>(entity =>
            {
                entity.ToTable("EmployeeAttribute", "hr");
            });

            modelBuilder.Entity<DocumentArt>(entity =>
            {
                entity.ToTable("DocumentArt", "ecm");
            });

            modelBuilder.Entity<Department>(entity =>
            {
                entity.ToTable("Department", "hr");
            });

            modelBuilder.Entity<CostCentre>(entity =>
            {
                entity.ToTable("CostCentre", "hr");
            });

            // 'AdWebAppToWebAppRole' tablosu güncellenmiş listeye dahil değil

            modelBuilder.Entity<WebAppUser>(entity =>
            {
                entity.ToTable("WebAppUser", "dbo");
            });

            // 'WebAppEmployeeInfo' tablosu güncellenmiş listeye dahil değil
        }

        protected static void OnModelCreating_ClassName(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Subsidiary>(entity =>
            {
                entity.ToTable("Subsidiary", "webapi");
            });

            modelBuilder.Entity<WindreamInputFolder>(entity =>
            {
                entity.ToTable("WindreamInputFolder", "webapi");
            });

            modelBuilder.Entity<WindreamSearchToDepartment>(entity =>
            {
                entity.ToTable("WindreamSearchToDepartment", "webapi");
            });

            modelBuilder.Entity<WindreamSearchItemToWindreamSearchToDepartment>(entity =>
            {
                entity.ToTable("WindreamSearchItemToWindreamSearchToDepartment", "webapi");
            });

            modelBuilder.Entity<WindreamSearchItem>(entity =>
            {
                entity.ToTable("WindreamSearchItem", "webapi");
            });

            modelBuilder.Entity<WindreamSearch>(entity =>
            {
                entity.ToTable("WindreamSearch", "webapi");
            });

            modelBuilder.Entity<WindreamIndexToWindreamSearchToDepartment>(entity =>
            {
                entity.ToTable("WindreamIndexToWindreamSearchToDepartment", "webapi");
            });

            modelBuilder.Entity<WindreamIndex>(entity =>
            {
                entity.ToTable("WindreamIndex", "webapi");
            });

            modelBuilder.Entity<WindreamColumnsToDepartment>(entity =>
            {
                entity.ToTable("WindreamColumnsToDepartment", "webapi");
            });

            modelBuilder.Entity<WebAppToWebAppRole>(entity =>
            {
                entity.ToTable("WebAppToWebAppRole", "webapi");
            });

            modelBuilder.Entity<WebAppToWebAppAdditionalRole>(entity =>
            {
                entity.ToTable("WebAppToWebAppAdditionalRole", "webapi");
            });

            modelBuilder.Entity<WebAppToDepartment>(entity =>
            {
                entity.ToTable("WebAppToDepartment", "webapi");
            });

            modelBuilder.Entity<WebAppAdditionalRole>(entity =>
            {
                entity.ToTable("WebAppAdditionalRole", "webapi");
            });

            modelBuilder.Entity<EmployeeToWebApp>(entity =>
            {
                entity.ToTable("EmployeeToWebApp", "webapi");
            });

            modelBuilder.Entity<EmployeeToDepartment>(entity =>
            {
                entity.ToTable("EmployeeToDepartment", "webapi");
            });

            modelBuilder.Entity<EmployeeToAttribute>(entity =>
            {
                entity.ToTable("EmployeeToAttribute", "webapi");
            });

            modelBuilder.Entity<Employee>(entity =>
            {
                entity.ToTable("Employee", "webapi");
            });

            modelBuilder.Entity<DocumentArtToDepartment>(entity =>
            {
                entity.ToTable("DocumentArtToDepartment", "webapi");
            });

            modelBuilder.Entity<DepartmentToWebAppToEmployeeForWindream>(entity =>
            {
                entity.ToTable("DepartmentToWebAppToEmployeeForWindream", "webapi");
            });

            modelBuilder.Entity<WebAppRole>(entity =>
            {
                entity.ToTable("WebAppRole", "webapi");
            });

            modelBuilder.Entity<WebApp>(entity =>
            {
                entity.ToTable("WebApp", "webapi");
            });

            modelBuilder.Entity<Rang>(entity =>
            {
                entity.ToTable("Rang", "webapi");
            });

            modelBuilder.Entity<Project>(entity =>
            {
                entity.ToTable("Project", "webapi");
            });

            modelBuilder.Entity<EmployeeStatus>(entity =>
            {
                entity.ToTable("EmployeeStatus", "webapi");
            });

            modelBuilder.Entity<EmployeeAttribute>(entity =>
            {
                entity.ToTable("EmployeeAttribute", "webapi");
            });

            modelBuilder.Entity<DocumentArt>(entity =>
            {
                entity.ToTable("DocumentArt", "webapi");
            });

            modelBuilder.Entity<Department>(entity =>
            {
                entity.ToTable("Department", "webapi");
            });

            modelBuilder.Entity<CostCentre>(entity =>
            {
                entity.ToTable("CostCentre", "webapi");
            });

            modelBuilder.Entity<AdWebAppToWebAppRole>(entity =>
            {
                entity.ToTable("AdWebAppToWebAppRole", "webapi");
            });


            modelBuilder.Entity<WebAppUser>(entity =>
            {
                entity.ToTable("WebAppUser", "webapi");
            });

            modelBuilder.Entity<WebAppEmployeeInfo>(entity =>
            {
                entity.ToTable("WebAppEmployeeInfo", "webapi");
            });
        }

        #region MODEL CREATIN FOR DIGIDAL-DATA NAMING
        protected static void OnModelCreating_DDSQLNaming(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Subsidiary>(entity =>
            {
                entity.ToTable("TBSTF_SUBSIDIARY", "dbo");
            });

            modelBuilder.Entity<WindreamInputFolder>(entity =>
            {
                entity.ToTable("TBSTF_WINDREAM_INPUT_FOLDER", "dbo");
            });

            modelBuilder.Entity<WindreamSearchToDepartment>(entity =>
            {
                entity.ToTable("TBSTF_WINDREAM_SEARCH_TO_DEPARTMENT", "dbo");
            });

            modelBuilder.Entity<WindreamSearchItemToWindreamSearchToDepartment>(entity =>
            {
                entity.ToTable("TBSTF_WINDREAM_SEARCH_ITEM_TO_WINDREAM_SEARCH_TO_DEPARTMENT", "dbo");
            });

            modelBuilder.Entity<WindreamSearchItem>(entity =>
            {
                entity.ToTable("TBSTF_WINDREAM_SEARCH_ITEM", "dbo");
            });

            modelBuilder.Entity<WindreamSearch>(entity =>
            {
                entity.ToTable("TBSTF_WINDREAM_SEARCH", "dbo");
            });

            modelBuilder.Entity<WindreamIndexToWindreamSearchToDepartment>(entity =>
            {
                entity.ToTable("TBSTF_WINDREAM_INDEX_TO_WINDREAM_SEARCH_TO_DEPARTMENT", "dbo");
            });

            modelBuilder.Entity<WindreamIndex>(entity =>
            {
                entity.ToTable("TBSTF_WINDREAM_INDEX", "dbo");
            });

            modelBuilder.Entity<WindreamColumnsToDepartment>(entity =>
            {
                entity.ToTable("TBSTF_WINDREAM_COLUMNS_TO_DEPARTMENT", "dbo");
            });

            modelBuilder.Entity<WebAppToWebAppRole>(entity =>
            {
                entity.ToTable("TBSTF_WEB_APP_TO_WEB_APP_ROLE", "dbo");
            });

            modelBuilder.Entity<WebAppToWebAppAdditionalRole>(entity =>
            {
                entity.ToTable("TBSTF_WEB_APP_TO_WEB_APP_ADDITIONAL_ROLE", "dbo");
            });

            modelBuilder.Entity<WebAppToDepartment>(entity =>
            {
                entity.ToTable("TBSTF_WEB_APP_TO_DEPARTMENT", "dbo");
            });

            modelBuilder.Entity<WebAppAdditionalRole>(entity =>
            {
                entity.ToTable("TBSTF_WEB_APP_ADDITIONAL_ROLE", "dbo");
            });

            modelBuilder.Entity<EmployeeToWebApp>(entity =>
            {
                entity.ToTable("TBSTF_EMPLOYEE_TO_WEB_APP", "dbo");
            });

            modelBuilder.Entity<EmployeeToDepartment>(entity =>
            {
                entity.ToTable("TBSTF_EMPLOYEE_TO_DEPARTMENT", "dbo");
            });

            modelBuilder.Entity<EmployeeToAttribute>(entity =>
            {
                entity.ToTable("TBSTF_EMPLOYEE_TO_ATTRIBUTE", "dbo");
            });

            modelBuilder.Entity<Employee>(entity =>
            {
                entity.ToTable("TBSTF_EMPLOYEE", "dbo");
            });

            modelBuilder.Entity<DocumentArtToDepartment>(entity =>
            {
                entity.ToTable("TBSTF_DOCUMENT_ART_TO_DEPARTMENT", "dbo");
            });

            modelBuilder.Entity<DepartmentToWebAppToEmployeeForWindream>(entity =>
            {
                entity.ToTable("TBSTF_DEPARTMENT_TO_WEB_APP_TO_EMPLOYEE_FOR_WINDREAM", "dbo");
            });

            modelBuilder.Entity<WebAppRole>(entity =>
            {
                entity.ToTable("TBSTF_WEB_APP_ROLE", "dbo");
            });

            modelBuilder.Entity<WebApp>(entity =>
            {
                entity.ToTable("TBSTF_WEB_APP", "dbo");
            });

            modelBuilder.Entity<Rang>(entity =>
            {
                entity.ToTable("TBSTF_RANG", "dbo");
            });

            modelBuilder.Entity<Project>(entity =>
            {
                entity.ToTable("TBSTF_PROJECT", "dbo");
            });

            modelBuilder.Entity<EmployeeStatus>(entity =>
            {
                entity.ToTable("TBSTF_EMPLOYEE_STATUS", "dbo");
            });

            modelBuilder.Entity<EmployeeAttribute>(entity =>
            {
                entity.ToTable("TBSTF_EMPLOYEE_ATTRIBUTE", "dbo");
            });

            modelBuilder.Entity<DocumentArt>(entity =>
            {
                entity.ToTable("TBSTF_DOCUMENT_ART", "dbo");
            });

            modelBuilder.Entity<Department>(entity =>
            {
                entity.ToTable("TBSTF_DEPARTMENT", "dbo");
            });

            modelBuilder.Entity<CostCentre>(entity =>
            {
                entity.ToTable("TBSTF_COST_CENTRE", "dbo");
            });

            modelBuilder.Entity<AdWebAppToWebAppRole>(entity =>
            {
                entity.ToTable("TBSTF_AD_WEB_APP_TO_WEB_APP_ROLE", "dbo");
            });

            modelBuilder.Entity<WebAppUser>(entity =>
            {
                entity.ToTable("TBSTF_WEB_APP_USER", "dbo");
            });

            modelBuilder.Entity<WebAppEmployeeInfo>(entity =>
            {
                entity.ToTable("TBSTF_WEB_APP_EMPLOYEE_INFO", "dbo");
            });

            Configure4DDNaming(modelBuilder.Model.GetEntityTypes().ToArray());
        }

        private static void Configure4DDNaming(params IMutableEntityType[] entityTypes)
        {
            foreach (var entityType in entityTypes)
            {
                // Configure column names
                foreach (var property in entityType.GetProperties())
                {
                    var columnName = ToSnakeCase(property.Name);
                    property.SetColumnName(columnName);
                }
            }
        }

        private static string ToSnakeCase(string input)
        {
            if (string.IsNullOrEmpty(input))
            {
                return input;
            }

            var startUnderscores = System.Text.RegularExpressions.Regex.Match(input, @"^_+");
            return startUnderscores + System.Text.RegularExpressions.Regex.Replace(input, @"([a-z0-9])([A-Z])", "$1_$2").ToUpper();
        }
        #endregion
    }
}
