using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using PARR.DAL.Cache.Services.Base;
using PARR.DAL.Configurations.DbSettings;
using PARR.DAL.Context;
using PARR.DAL.Contracts;
using PARR.DAL.DomainServices.Implementations;
using PARR.DAL.DomainServices.Interfaces;
using PARR.DAL.DomainServices.Shortcodes;
using PARR.DAL.InfluxDbServices;
using PARR.DAL.NextRunServices;
using PARR.DAL.NextRunServices.Subservices;
using PARR.DAL.Services.Implementation;
using PARR.DAL.Services.Implementations;
using PARR.DAL.Services.Implementations.Job;
using PARR.DAL.Services.Implementations.Schedule;
using PARR.DAL.Services.Implementations.Unit;
using PARR.DAL.Services.Interfaces;
using PARR.DAL.Services.Interfaces.Job;
using PARR.DAL.Services.Interfaces.Schedule;
using PARR.DAL.Services.Interfaces.Unit;
using PARR.DAL.Settings;
using PARR.DAL.TransformServices;
using System.ComponentModel;

namespace PARR.DAL
{
    public static class ParrDalInstaller
    {
        /// <summary>
        /// Устанавливает Dal сервисы (1)
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void InstallDalServices(this IServiceCollection services, IConfiguration configuration)
        {
            //.EnableSensitiveDataLogging() - вкл подробное логирование при применении миграций, на проде выключить
            services.AddDbContext<DataContext>(opt =>
              opt
                .EnableSensitiveDataLogging()
                .UseNpgsql(configuration.GetConnectionString("DefaultConnection"))
            );

            #region Redis + cache services

            services.AddStackExchangeRedisCache(opt =>
            {
                opt.Configuration = configuration.GetConnectionString("RedisConnection");
            });

            var groupedShortcodesCacheSettings = new GroupedShortcodesCacheSettings();
            configuration.GetSection(nameof(GroupedShortcodesCacheSettings)).Bind(groupedShortcodesCacheSettings);
            services.AddSingleton(groupedShortcodesCacheSettings);

            services.AddTransient<IRedisCacheService, RedisCacheService>();

            #endregion

            #region InfluxDb

            var influxDbSettings = new InfluxDbSettings();
            configuration.GetSection(nameof(InfluxDbSettings)).Bind(influxDbSettings);
            services.AddSingleton(influxDbSettings);

            services.AddTransient<IInfluxDbService, InfluxDbService>();

            #endregion


            // Entity services
            services.AddTransient<IHostService, HostService>();
            services.AddTransient<IWorkGroupService, WorkGroupService>();
            services.AddTransient<IApplicationService, ApplicationService>();
            services.AddTransient<IApplicationTypeService, ApplicationTypeService>();
            services.AddTransient<IApplicationInHostService, ApplicationInHostService>();
            services.AddTransient<IApplicationsInWorkService, ApplicationsInWorkService>();
            services.AddTransient<IApplicationService, ApplicationService>();
            services.AddTransient<IProcessService, ProcessService>();
            services.AddTransient<ISubprocessService, SubprocessService>();
            services.AddTransient<ITnkService, TnkService>();
            services.AddTransient<ITemplateService, TemplateService>();
            services.AddTransient<IStatusTemplateService, StatusTemplateService>();
            services.AddTransient<IRobotHistoryLevelService, RobotHistoryLevelService>();
            services.AddTransient<IRobotStatusService, RobotStatusService>();
            services.AddTransient<IRobotService, RobotService>();
            services.AddTransient<IRobotConfigurationService, RobotConfigurationService>();
            services.AddTransient<IRobotHistoryService, RobotHistoryService>();
            services.AddTransient<IEsppSchTypeConfigService, EsppSchTypeConfigService>();
            services.AddTransient<IAgentHistoryService, AgentHistoryService>();
            services.AddTransient<IOrderService, OrderService>();
            services.AddTransient<IOrderStatusService, OrderStatusService>();
            services.AddTransient<IUserService, UserService>();
            services.AddTransient<IRoleService, RoleService>();
            services.AddTransient<ITaskStatusService, TaskStatusService>();
            services.AddTransient<IEkStatusService, EkStatusService>();
            services.AddTransient<IEsppSchTypeScheduleService, EsppSchTypeScheduleService>();
            services.AddTransient<IWeekendDayService, WeekendDayService>();
            services.AddTransient<IDistributionPeriodService, DistributionPeriodService>();
            services.AddTransient<IEsppSchTypeValueService, EsppSchTypeValueService>();
            services.AddTransient<IResponseAreaService, ResponseAreaService>();
            services.AddTransient<ITemplateHistoryService, TemplateHistoryService>();
            services.AddTransient<IParrComponentService, ParrComponentService>();
            services.AddTransient<ITemplateStatusTypeService, TemplateStatusTypeService>();

            #region Schedule 

            services.AddTransient<IScheduleExcludeTypeService, ScheduleExcludeTypeService>();
            services.AddTransient<IScheduleExcludeTypeCalendarService, ScheduleExcludeTypeCalendarService>();

            #endregion

            #region Unit

            services.AddTransient<IUnitService, UnitService>();
            services.AddTransient<IUnitFieldValueService, UnitFieldValueService>();
            services.AddTransient<IUnitFieldService, UnitFieldService>();
            services.AddTransient<IUnitInUnitService, UnitInUnitService>();
            services.AddTransient<IUnitInValueService, UnitInValueService>();
            services.AddTransient<IUnitRegionalEkPtkGroupService, UnitRegionalEkPtkGroupService>();
            services.AddTransient<IUnitKiiUnitService, UnitKiiUnitService>();

            #endregion

            #region Job

            services.AddTransient<IJobService, JobService>();
            services.AddTransient<IJobGroupService, JobGroupService>();
            services.AddTransient<IJobGroupTypeService, JobGroupTypeService>();
            services.AddTransient<IJobUnitFilterService, JobUnitFilterService>();
            services.AddTransient<IFieldFilterService, FieldFilterService>();
            services.AddTransient<IJobUnitFilterService, JobUnitFilterService>();
            services.AddTransient<IJobAutoControlService, JobAutoControlService>();

            #endregion

            // TransformServices
            services.AddTransient<IEsppScheduleTransformService, EsppScheduleTransformService>();
            services.AddTransient<INextRunModifierService, NextRunModifierService>();

            #region NextRun Services

            services.AddTransient<INextRunService, NextRunService>();
            services.AddTransient<ITemplateDistributor, TemplateDistributor>();

            #endregion


            #region DomainServces
            services.AddTransient<IShortcodesService, ShortcodesService>();
            services.AddTransient<IUnitFilterService, UnitFilterService>();
            services.AddTransient<IMatchingStatusService, MatchingStatusService>();
            #endregion


        }

        /// <summary>
        /// Добавляет конфигурацию Dal (2)
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IConfigurationBuilder AddDalConfigurations(this IConfigurationBuilder builder, IServiceCollection services)
        {
            builder.Add(new DBConfigurationSource(services));

            return builder;
        }

        /// <summary>
        /// Добавляет конфигурацию в сервисы (3)
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddDallSettings(this IServiceCollection services, IConfiguration configuration)
        {
            //SettingsFromDb configuration
            var settingsFromDb = new SettingsFromDb();
            configuration.GetSection(nameof(SettingsFromDb)).Bind(settingsFromDb);
            services.AddSingleton(settingsFromDb);

            PrefixSettings.PrefixWithoutVariable = settingsFromDb.TemplatePrefixWithoutVariable;
        }

    }
}
