using System;
using System.Linq;
using Microsoft.Extensions.Options;
using StellaOps.Feedser.Source.CertCc.Configuration;
using StellaOps.Feedser.Source.CertCc.Internal;
using StellaOps.Feedser.Source.Common.Cursors;
using Xunit;

namespace StellaOps.Feedser.Source.CertCc.Tests.Internal;

public sealed class CertCcSummaryPlannerTests
{
    [Fact]
    public void CreatePlan_UsesInitialBackfillWindow()
    {
        var options = Options.Create(new CertCcOptions
        {
            SummaryWindow = new TimeWindowCursorOptions
            {
                WindowSize = TimeSpan.FromDays(30),
                Overlap = TimeSpan.FromDays(3),
                InitialBackfill = TimeSpan.FromDays(120),
                MinimumWindowSize = TimeSpan.FromDays(1),
            },
        });

        var timeProvider = new TestTimeProvider(DateTimeOffset.Parse("2025-10-10T12:00:00Z"));
        var planner = new CertCcSummaryPlanner(options, timeProvider);

        var plan = planner.CreatePlan(state: null);

        Assert.Equal(DateTimeOffset.Parse("2025-06-12T12:00:00Z"), plan.Window.Start);
        Assert.Equal(DateTimeOffset.Parse("2025-07-12T12:00:00Z"), plan.Window.End);

        Assert.Equal(3, plan.Requests.Count);

        var monthly = plan.Requests.Where(r => r.Scope == CertCcSummaryScope.Monthly).ToArray();
        Assert.Collection(monthly,
            request =>
            {
                Assert.Equal(2025, request.Year);
                Assert.Equal(6, request.Month);
                Assert.Equal("https://www.kb.cert.org/vuls/api/2025/06/summary/", request.Uri.AbsoluteUri);
            },
            request =>
            {
                Assert.Equal(2025, request.Year);
                Assert.Equal(7, request.Month);
                Assert.Equal("https://www.kb.cert.org/vuls/api/2025/07/summary/", request.Uri.AbsoluteUri);
            });

        var yearly = plan.Requests.Where(r => r.Scope == CertCcSummaryScope.Yearly).ToArray();
        Assert.Single(yearly);
        Assert.Equal(2025, yearly[0].Year);
        Assert.Null(yearly[0].Month);
        Assert.Equal("https://www.kb.cert.org/vuls/api/2025/summary/", yearly[0].Uri.AbsoluteUri);

        Assert.Equal(plan.Window.End, plan.NextState.LastWindowEnd);
    }

    [Fact]
    public void CreatePlan_AdvancesWindowRespectingOverlap()
    {
        var options = Options.Create(new CertCcOptions
        {
            SummaryWindow = new TimeWindowCursorOptions
            {
                WindowSize = TimeSpan.FromDays(30),
                Overlap = TimeSpan.FromDays(10),
                InitialBackfill = TimeSpan.FromDays(90),
                MinimumWindowSize = TimeSpan.FromDays(1),
            },
        });

        var timeProvider = new TestTimeProvider(DateTimeOffset.Parse("2025-12-01T00:00:00Z"));
        var planner = new CertCcSummaryPlanner(options, timeProvider);

        var first = planner.CreatePlan(null);
        var second = planner.CreatePlan(first.NextState);

        Assert.True(second.Window.Start < second.Window.End);
        Assert.Equal(first.Window.End - options.Value.SummaryWindow.Overlap, second.Window.Start);
    }

    private sealed class TestTimeProvider : TimeProvider
    {
        private DateTimeOffset _now;

        public TestTimeProvider(DateTimeOffset now) => _now = now;

        public override DateTimeOffset GetUtcNow() => _now;

        public void Advance(TimeSpan delta) => _now = _now.Add(delta);
    }
}
