using System;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using StellaOps.Feedser.Core.Jobs;
using StellaOps.Feedser.Source.Common.Http;
using StellaOps.Feedser.Source.Ghsa;
using StellaOps.Feedser.Source.Ghsa.Configuration;
using Xunit;

namespace StellaOps.Feedser.Source.Ghsa.Tests.Ghsa;

public sealed class GhsaDependencyInjectionRoutineTests
{
    [Fact]
    public void Register_ConfiguresConnectorAndScheduler()
    {
        var services = new ServiceCollection();
        services.AddLogging(builder => builder.AddProvider(NullLoggerProvider.Instance));
        services.AddOptions();
        services.AddSourceCommon();

        var configuration = new ConfigurationBuilder()
            .AddInMemoryCollection(new Dictionary<string, string?>
            {
                ["feedser:sources:ghsa:apiToken"] = "test-token",
                ["feedser:sources:ghsa:pageSize"] = "25",
                ["feedser:sources:ghsa:maxPagesPerFetch"] = "3",
                ["feedser:sources:ghsa:initialBackfill"] = "1.00:00:00",
            })
            .Build();

        var routine = new GhsaDependencyInjectionRoutine();
        routine.Register(services, configuration);

        services.Configure<JobSchedulerOptions>(_ => { });

        var provider = services.BuildServiceProvider(validateScopes: true);

        var ghsaOptions = provider.GetRequiredService<IOptions<GhsaOptions>>().Value;
        Assert.Equal("test-token", ghsaOptions.ApiToken);
        Assert.Equal(25, ghsaOptions.PageSize);
        Assert.Equal(TimeSpan.FromDays(1), ghsaOptions.InitialBackfill);

        var schedulerOptions = provider.GetRequiredService<IOptions<JobSchedulerOptions>>().Value;
        Assert.True(schedulerOptions.Definitions.TryGetValue(GhsaJobKinds.Fetch, out var fetchDefinition));
        Assert.True(schedulerOptions.Definitions.TryGetValue(GhsaJobKinds.Parse, out var parseDefinition));
        Assert.True(schedulerOptions.Definitions.TryGetValue(GhsaJobKinds.Map, out var mapDefinition));

        Assert.Equal(typeof(GhsaFetchJob), fetchDefinition.JobType);
        Assert.Equal(TimeSpan.FromMinutes(6), fetchDefinition.Timeout);
        Assert.Equal(TimeSpan.FromMinutes(4), fetchDefinition.LeaseDuration);
        Assert.Equal("1,11,21,31,41,51 * * * *", fetchDefinition.CronExpression);
        Assert.True(fetchDefinition.Enabled);

        Assert.Equal(typeof(GhsaParseJob), parseDefinition.JobType);
        Assert.Equal(TimeSpan.FromMinutes(5), parseDefinition.Timeout);
        Assert.Equal(TimeSpan.FromMinutes(4), parseDefinition.LeaseDuration);
        Assert.Equal("3,13,23,33,43,53 * * * *", parseDefinition.CronExpression);
        Assert.True(parseDefinition.Enabled);

        Assert.Equal(typeof(GhsaMapJob), mapDefinition.JobType);
        Assert.Equal(TimeSpan.FromMinutes(5), mapDefinition.Timeout);
        Assert.Equal(TimeSpan.FromMinutes(4), mapDefinition.LeaseDuration);
        Assert.Equal("5,15,25,35,45,55 * * * *", mapDefinition.CronExpression);
        Assert.True(mapDefinition.Enabled);
    }
}
