using GmRelay.Bot.Features.Sessions.RescheduleSession;

namespace GmRelay.Bot.Tests.Features.Sessions.RescheduleSession;

public sealed class HandleRescheduleTimeInputHandlerTests
{
    [Fact]
    public void TryParseVotingInput_ShouldAcceptTwoOptionsAndDeadline()
    {
        var now = new DateTimeOffset(2026, 4, 24, 8, 0, 0, TimeSpan.Zero);

        var ok = RescheduleVotingInput.TryParse(
            """
            25.04.2026 19:30
            26.04.2026 18:00
            Дедлайн: 25.04.2026 12:00
            """,
            now,
            out var input,
            out var error);

        Assert.True(ok, error);
        Assert.Equal(2, input.Options.Count);
        Assert.Equal(new DateTimeOffset(2026, 4, 25, 16, 30, 0, TimeSpan.Zero), input.Options[0]);
        Assert.Equal(new DateTimeOffset(2026, 4, 26, 15, 0, 0, TimeSpan.Zero), input.Options[1]);
        Assert.Equal(new DateTimeOffset(2026, 4, 25, 9, 0, 0, TimeSpan.Zero), input.Deadline);
    }

    [Fact]
    public void TryParseVotingInput_ShouldRejectSingleOption()
    {
        var now = new DateTimeOffset(2026, 4, 24, 8, 0, 0, TimeSpan.Zero);

        var ok = RescheduleVotingInput.TryParse(
            """
            25.04.2026 19:30
            Дедлайн: 25.04.2026 12:00
            """,
            now,
            out _,
            out var error);

        Assert.False(ok);
        Assert.Equal("Укажите от 2 до 3 вариантов времени.", error);
    }

    [Fact]
    public void BuildVotingMessage_ShouldShowOptionsDeadlineVotesAndPendingParticipants()
    {
        var firstOptionId = Guid.NewGuid();
        var secondOptionId = Guid.NewGuid();
        var aliceId = Guid.NewGuid();
        var bobId = Guid.NewGuid();
        var charlieId = Guid.NewGuid();
        var currentTime = new DateTime(2026, 4, 25, 16, 30, 0, DateTimeKind.Utc);
        var deadline = new DateTimeOffset(2026, 4, 25, 9, 0, 0, TimeSpan.Zero);
        var options = new List<RescheduleOptionDto>
        {
            new(firstOptionId, 1, new DateTimeOffset(2026, 4, 26, 16, 0, 0, TimeSpan.Zero)),
            new(secondOptionId, 2, new DateTimeOffset(2026, 4, 27, 17, 0, 0, TimeSpan.Zero))
        };
        var participants = new List<VoteParticipantDto>
        {
            new(aliceId, "Alice", "alice"),
            new(bobId, "Bob", null),
            new(charlieId, "Charlie", null)
        };
        var votes = new List<RescheduleOptionVoteDto>
        {
            new(firstOptionId, aliceId, "Alice", "alice"),
            new(secondOptionId, bobId, "Bob", null)
        };

        var text = HandleRescheduleTimeInputHandler.BuildVotingMessage(
            "Shadowrun",
            currentTime,
            deadline,
            options,
            participants,
            votes);

        Assert.Contains("Shadowrun", text);
        Assert.Contains("Дедлайн: <b>25 апреля 2026, 12:00</b> (МСК)", text);
        Assert.Contains("1. <b>26 апреля 2026, 19:00</b> (МСК) — 1 голос", text);
        Assert.Contains("@alice", text);
        Assert.Contains("2. <b>27 апреля 2026, 20:00</b> (МСК) — 1 голос", text);
        Assert.Contains("Bob", text);
        Assert.Contains("Не проголосовали: Charlie", text);
        Assert.Contains("Голосов: 2/3", text);
    }

    [Fact]
    public void BuildVotingKeyboard_ShouldCreateOneButtonPerOption()
    {
        var firstOptionId = Guid.NewGuid();
        var secondOptionId = Guid.NewGuid();
        var options = new List<RescheduleOptionDto>
        {
            new(firstOptionId, 1, new DateTimeOffset(2026, 4, 26, 16, 0, 0, TimeSpan.Zero)),
            new(secondOptionId, 2, new DateTimeOffset(2026, 4, 27, 17, 0, 0, TimeSpan.Zero))
        };

        var keyboard = HandleRescheduleTimeInputHandler.BuildVotingKeyboard(options);
        var buttons = keyboard.InlineKeyboard.SelectMany(row => row).ToList();

        Assert.Collection(
            buttons,
            button =>
            {
                Assert.Equal("1. 26.04 19:00", button.Text);
                Assert.Equal($"reschedule_vote:{firstOptionId}", button.CallbackData);
            },
            button =>
            {
                Assert.Equal("2. 27.04 20:00", button.Text);
                Assert.Equal($"reschedule_vote:{secondOptionId}", button.CallbackData);
            });
    }
}
