using GmRelay.Shared.Domain;
using GmRelay.Shared.Rendering;

namespace GmRelay.Bot.Tests.Rendering;

public sealed class SessionBatchViewBuilderTests
{
    [Fact]
    public void Build_ShouldOrderSessionsByDate()
    {
        var firstSessionId = Guid.NewGuid();
        var secondSessionId = Guid.NewGuid();
        var cancelledSessionId = Guid.NewGuid();

        var sessions = new[]
        {
            new SessionBatchDto(secondSessionId, new DateTime(2026, 4, 27, 18, 0, 0, DateTimeKind.Utc), SessionStatus.Planned, 4, "https://example.com/game"),
            new SessionBatchDto(cancelledSessionId, new DateTime(2026, 4, 28, 18, 0, 0, DateTimeKind.Utc), SessionStatus.Cancelled, null, ""),
            new SessionBatchDto(firstSessionId, new DateTime(2026, 4, 26, 18, 0, 0, DateTimeKind.Utc), SessionStatus.Planned, 2, "https://example.com/game")
        };
        var participants = new[]
        {
            new ParticipantBatchDto(secondSessionId, "Alice", "alice", ParticipantRegistrationStatus.Active),
            new ParticipantBatchDto(secondSessionId, "Charlie", null, ParticipantRegistrationStatus.Waitlisted),
            new ParticipantBatchDto(cancelledSessionId, "Bob", null, ParticipantRegistrationStatus.Active)
        };

        var result = SessionBatchViewBuilder.Build("Campaign", sessions, participants);

        Assert.Equal("Campaign", result.Title);
        Assert.Equal(3, result.Sessions.Count);
        Assert.Equal(firstSessionId, result.Sessions[0].SessionId);
        Assert.Equal(secondSessionId, result.Sessions[1].SessionId);
        Assert.Equal(cancelledSessionId, result.Sessions[2].SessionId);
    }

    [Fact]
    public void Build_ShouldCalculatePlayerCounts()
    {
        var sessionId = Guid.NewGuid();
        var sessions = new[] { new SessionBatchDto(sessionId, DateTime.UtcNow, SessionStatus.Planned, 4, "https://example.com/game") };
        var participants = new[]
        {
            new ParticipantBatchDto(sessionId, "Alice", "alice", ParticipantRegistrationStatus.Active),
            new ParticipantBatchDto(sessionId, "Bob", null, ParticipantRegistrationStatus.Active),
            new ParticipantBatchDto(sessionId, "Charlie", null, ParticipantRegistrationStatus.Waitlisted)
        };

        var result = SessionBatchViewBuilder.Build("Test", sessions, participants);
        var session = result.Sessions[0];

        Assert.Equal(2, session.ActivePlayerCount);
        Assert.Equal(4, session.MaxPlayers);
        Assert.True(session.ActivePlayers.Count == 2);
        Assert.True(session.WaitlistedPlayers.Count == 1);
    }

    [Fact]
    public void Build_ShouldIncludeActionsForActiveSessions()
    {
        var sessionId = Guid.NewGuid();
        var sessions = new[] { new SessionBatchDto(sessionId, DateTime.UtcNow, SessionStatus.Planned, 4, "https://example.com/game") };
        var participants = Array.Empty<ParticipantBatchDto>();

        var result = SessionBatchViewBuilder.Build("Test", sessions, participants);
        var actions = result.Sessions[0].AvailableActions;

        Assert.Equal(2, actions.Count);
        Assert.Equal("join_session", result.Sessions[0].AvailableActions[0].ActionKey);
        Assert.Equal("leave_session", result.Sessions[0].AvailableActions[1].ActionKey);
        Assert.Equal(sessionId, actions[0].SessionId);
        Assert.Equal(sessionId, actions[1].SessionId);
    }

    [Fact]
    public void Build_ShouldNotIncludeActionsForCancelledSessions()
    {
        var sessionId = Guid.NewGuid();
        var sessions = new[] { new SessionBatchDto(sessionId, DateTime.UtcNow, SessionStatus.Cancelled, null, "") };
        var participants = Array.Empty<ParticipantBatchDto>();

        var result = SessionBatchViewBuilder.Build("Test", sessions, participants);

        Assert.Empty(result.Sessions[0].AvailableActions);
    }

    [Fact]
    public void Build_ShouldMarkWaitlistActionWhenFull()
    {
        var sessionId = Guid.NewGuid();
        var sessions = new[] { new SessionBatchDto(sessionId, DateTime.UtcNow, SessionStatus.Planned, 1, "https://example.com/game") };
        var participants = new[] { new ParticipantBatchDto(sessionId, "Alice", "alice", ParticipantRegistrationStatus.Active) };

        var result = SessionBatchViewBuilder.Build("Test", sessions, participants);
        var joinAction = result.Sessions[0].AvailableActions.First(a => a.ActionKey == "join_session");

        Assert.Contains("ожидания", joinAction.Label);
    }

    [Fact]
    public void Build_ShouldIncludePlayerUsernames()
    {
        var sessionId = Guid.NewGuid();
        var sessions = new[] { new SessionBatchDto(sessionId, DateTime.UtcNow, SessionStatus.Planned, null, "https://example.com/game") };
        var participants = new[] { new ParticipantBatchDto(sessionId, "Alice", "alice", ParticipantRegistrationStatus.Active) };

        var result = SessionBatchViewBuilder.Build("Test", sessions, participants);
        var player = result.Sessions[0].ActivePlayers[0];

        Assert.Equal("Alice", player.DisplayName);
        Assert.Equal("alice", player.TelegramUsername);
    }
}
