using GmRelay.Web.Services;

namespace GmRelay.Bot.Tests.Web;

public sealed class BatchSchedulePlannerTests
{
    [Fact]
    public void BuildFixedIntervalSchedule_OrdersSessionsAndAppliesInterval()
    {
        var firstScheduledAt = new DateTime(2026, 5, 4, 16, 0, 0, DateTimeKind.Utc);
        var currentSchedule = new[]
        {
            new DateTime(2026, 4, 28, 16, 0, 0, DateTimeKind.Utc),
            new DateTime(2026, 4, 21, 16, 0, 0, DateTimeKind.Utc),
            new DateTime(2026, 5, 5, 16, 0, 0, DateTimeKind.Utc)
        };

        var result = BatchSchedulePlanner.BuildFixedIntervalSchedule(currentSchedule, firstScheduledAt, intervalDays: 7);

        Assert.Equal(
            [
                firstScheduledAt,
                firstScheduledAt.AddDays(7),
                firstScheduledAt.AddDays(14)
            ],
            result);
    }

    [Fact]
    public void BuildFixedIntervalSchedule_RejectsNonPositiveInterval()
    {
        var currentSchedule = new[] { new DateTime(2026, 4, 28, 16, 0, 0, DateTimeKind.Utc) };
        var firstScheduledAt = new DateTime(2026, 5, 4, 16, 0, 0, DateTimeKind.Utc);

        var action = () => BatchSchedulePlanner.BuildFixedIntervalSchedule(currentSchedule, firstScheduledAt, intervalDays: 0);

        Assert.Throws<ArgumentOutOfRangeException>(action);
    }

    [Fact]
    public void BuildRecurringSchedule_CreatesFixedIntervalScheduleFromFirstDate()
    {
        var firstScheduledAt = new DateTime(2026, 5, 4, 16, 0, 0, DateTimeKind.Utc);

        var result = BatchSchedulePlanner.BuildRecurringSchedule(firstScheduledAt, sessionCount: 3, intervalDays: 14);

        Assert.Equal(
            [
                firstScheduledAt,
                firstScheduledAt.AddDays(14),
                firstScheduledAt.AddDays(28)
            ],
            result);
    }

    [Theory]
    [InlineData(0, 7)]
    [InlineData(53, 7)]
    [InlineData(3, 0)]
    public void BuildRecurringSchedule_RejectsInvalidTemplateShape(int sessionCount, int intervalDays)
    {
        var firstScheduledAt = new DateTime(2026, 5, 4, 16, 0, 0, DateTimeKind.Utc);

        var action = () => BatchSchedulePlanner.BuildRecurringSchedule(firstScheduledAt, sessionCount, intervalDays);

        Assert.Throws<ArgumentOutOfRangeException>(action);
    }

    [Theory]
    [InlineData(BatchCloneInterval.NextWeek, 2026, 5, 8)]
    [InlineData(BatchCloneInterval.NextMonth, 2026, 6, 1)]
    public void ShiftForClone_AppliesRequestedCalendarShift(BatchCloneInterval interval, int expectedYear, int expectedMonth, int expectedDay)
    {
        var scheduledAt = new DateTime(2026, 5, 1, 16, 30, 0, DateTimeKind.Utc);

        var result = BatchSchedulePlanner.ShiftForClone(scheduledAt, interval);

        Assert.Equal(new DateTime(expectedYear, expectedMonth, expectedDay, 16, 30, 0, DateTimeKind.Utc), result);
    }
}
