using System.IO;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using StellaOps.Plugin;
using StellaOps.Excititor.Connectors.RedHat.CSAF.DependencyInjection;
using StellaOps.Excititor.Worker.Options;
using StellaOps.Excititor.Worker.Scheduling;

var builder = Host.CreateApplicationBuilder(args);
var services = builder.Services;
var configuration = builder.Configuration;
services.AddOptions<VexWorkerOptions>()
    .Bind(configuration.GetSection("Excititor:Worker"))
    .ValidateOnStart();

services.Configure<VexWorkerPluginOptions>(configuration.GetSection("Excititor:Worker:Plugins"));
services.AddRedHatCsafConnector();

services.AddSingleton<IValidateOptions<VexWorkerOptions>, VexWorkerOptionsValidator>();
services.AddSingleton(TimeProvider.System);
services.PostConfigure<VexWorkerOptions>(options =>
{
    if (!options.Providers.Any(provider => string.Equals(provider.ProviderId, "excititor:redhat", StringComparison.OrdinalIgnoreCase)))
    {
        options.Providers.Add(new VexWorkerProviderOptions
        {
            ProviderId = "excititor:redhat",
        });
    }
});
services.AddSingleton<PluginCatalog>(provider =>
{
    var pluginOptions = provider.GetRequiredService<IOptions<VexWorkerPluginOptions>>().Value;
    var catalog = new PluginCatalog();

    var directory = pluginOptions.ResolveDirectory();
    if (Directory.Exists(directory))
    {
        catalog.AddFromDirectory(directory, pluginOptions.ResolveSearchPattern());
    }
    else
    {
        var logger = provider.GetRequiredService<ILogger<Program>>();
        logger.LogWarning("Excititor worker plugin directory '{Directory}' does not exist; proceeding without external connectors.", directory);
    }

    return catalog;
});

services.AddSingleton<IVexProviderRunner, DefaultVexProviderRunner>();
services.AddHostedService<VexWorkerHostedService>();

var host = builder.Build();
await host.RunAsync();

public partial class Program;
