using FKGees;
using FKGees.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using NLog;
using NLog.Extensions.Logging;

var logger = LogManager.GetCurrentClassLogger();

AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
{
    var logger = LogManager.Setup()
        .LoadConfigurationFromFile("nlog.config")
        .GetCurrentClassLogger();
    logger.Fatal((Exception) e.ExceptionObject, "UnhandledException - aplication terminated");
    Environment.Exit(1);
};

TaskScheduler.UnobservedTaskException += (sender, e) =>
{
    var logger = LogManager.Setup()
        .LoadConfigurationFromFile("nlog.config")
        .GetCurrentClassLogger();
    logger.Fatal(e.Exception, "UnobservedTaskException - aplication terminated");
    Environment.Exit(1);
};

try
{
    var config = new ConfigurationBuilder()
        .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .Build();

    var servicesProvider = AddServices(config)
        .BuildServiceProvider();

    using (servicesProvider)
    {
        logger.Info("Run application");

        if (!Directory.Exists("Export"))
            Directory.CreateDirectory("Export");

        var app = servicesProvider.GetRequiredService<App>();
        app.Run(args)
            .Wait();
    }
}
catch (Exception ex)
{
    logger.Error(ex, "Stopped program because of exception");
    throw;
}
finally
{
    LogManager.Shutdown();
}

static IServiceCollection AddServices(IConfiguration config)
{
    var connectionString =
        $"Server={config[Constants.DbConfig.Host]},{config[Constants.DbConfig.Port]};Database={config[Constants.DbConfig.Database]};User Id={config[Constants.DbConfig.Login]}; Password={config[Constants.DbConfig.Password]};TrustServerCertificate=True";

    if (!int.TryParse(config[Constants.DbConfig.Timeout], out var dbTimeout) || dbTimeout < 30)
    {
        dbTimeout = 30;
    }

    var symbolMag = config["SymbolMag"] ?? string.Empty;
    var nazwaPlikuRejestry = config["NazwaPlikuRejestry"] ?? "rejestry.txt";
    var nazwaPlikuDekrety = config["NazwaPlikuDekrety"] ?? "dekrety.txt";
    var context = new Context
    {
        SymbolMag = symbolMag,
        RegistersFileName = nazwaPlikuRejestry,
        DecretsFileName = nazwaPlikuDekrety
    };

    var services = new ServiceCollection()
        .AddLogging(loggingBuilder =>
        {
            loggingBuilder.ClearProviders();
            loggingBuilder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
            loggingBuilder.AddNLog(config);
        })
        .AddSingleton<App>()
        .AddSingleton(context)
        .AddTransient<CsvService>()
        .AddScoped<DecretsService>()
        .AddScoped<RegistersService>()
        .AddRegistersDefinitions()
        .AddDecretsDefinitions()
        .AddTransient<PcmService>()
        .AddDbContextFactory<PcmDbContext>(options =>
        {
            options.UseSqlServer(connectionString, o =>
            {
                o.CommandTimeout(dbTimeout);
            });
            options.UseModel(Blink.Backoffice.Services.PcmDb.CompiledEntities.PcmDbContextModel.Instance);
            options.EnableSensitiveDataLogging(false);
        });

    return services;
}