using System;
using System.IO;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using StellaOps.DependencyInjection;
using StellaOps.Feedser.Core.Jobs;
using StellaOps.Feedser.Storage.Mongo.Exporting;

namespace StellaOps.Feedser.Exporter.Json;

public sealed class JsonExporterDependencyInjectionRoutine : IDependencyInjectionRoutine
{
    private const string ConfigurationSection = "feedser:exporters:json";

    public IServiceCollection Register(IServiceCollection services, IConfiguration configuration)
    {
        ArgumentNullException.ThrowIfNull(services);
        ArgumentNullException.ThrowIfNull(configuration);

        services.TryAddSingleton<IJsonExportPathResolver, VulnListJsonExportPathResolver>();
        services.TryAddSingleton<ExportStateManager>();

        services.AddOptions<JsonExportOptions>()
            .Bind(configuration.GetSection(ConfigurationSection))
            .PostConfigure(static options =>
            {
                if (string.IsNullOrWhiteSpace(options.OutputRoot))
                {
                    options.OutputRoot = Path.Combine("exports", "json");
                }

                if (string.IsNullOrWhiteSpace(options.DirectoryNameFormat))
                {
                    options.DirectoryNameFormat = "yyyyMMdd'T'HHmmss'Z'";
                }
            });

        services.AddSingleton<JsonFeedExporter>();
        services.AddTransient<JsonExportJob>();

        services.PostConfigure<JobSchedulerOptions>(options =>
        {
            if (!options.Definitions.ContainsKey(JsonExportJob.JobKind))
            {
                options.Definitions[JsonExportJob.JobKind] = new JobDefinition(
                    JsonExportJob.JobKind,
                    typeof(JsonExportJob),
                    JsonExportJob.DefaultTimeout,
                    JsonExportJob.DefaultLeaseDuration,
                    null,
                    true);
            }
        });

        return services;
    }
}
