namespace GmRelay.Bot.Tests.Discord;

public sealed class DiscordSessionInteractionModuleSourceTests
{
    [Fact]
    public async Task Module_ShouldRouteJoinAndLeaveButtonsToNeutralHandlers()
    {
        var source = await ReadRepositoryFileAsync("src/GmRelay.DiscordBot/Features/Sessions/DiscordSessionInteractionModule.cs");

        Assert.Contains("ComponentInteractionModule<ButtonInteractionContext>", source, StringComparison.Ordinal);
        Assert.Contains("[ComponentInteraction(\"join_session\")]", source, StringComparison.Ordinal);
        Assert.Contains("[ComponentInteraction(\"leave_session\")]", source, StringComparison.Ordinal);
        Assert.Contains("JoinSessionHandler", source, StringComparison.Ordinal);
        Assert.Contains("LeaveSessionHandler", source, StringComparison.Ordinal);
        Assert.Contains("DiscordSessionInteractionMapper.CreateJoinCommand", source, StringComparison.Ordinal);
        Assert.Contains("DiscordSessionInteractionMapper.CreateLeaveCommand", source, StringComparison.Ordinal);
        Assert.Contains("RespondAsync", source, StringComparison.Ordinal);
        Assert.Contains("InteractionCallback.DeferredMessage(MessageFlags.Ephemeral)", source, StringComparison.Ordinal);
        Assert.Contains("ModifyResponseAsync", source, StringComparison.Ordinal);
        Assert.Contains("Не удалось обработать кнопку.", source, StringComparison.Ordinal);
        Assert.Contains("MessageFlags.Ephemeral", source, StringComparison.Ordinal);
    }

    [Fact]
    public async Task Module_ShouldUpdateSourceScheduleMessageThroughComponentInteraction()
    {
        var source = await ReadRepositoryFileAsync("src/GmRelay.DiscordBot/Features/Sessions/DiscordSessionInteractionModule.cs");

        Assert.Contains("InteractionCallback.DeferredModifyMessage", source, StringComparison.Ordinal);
        Assert.Contains("DiscordSessionBatchRenderer.Render", source, StringComparison.Ordinal);
        Assert.Contains("FollowupAsync", source, StringComparison.Ordinal);
        Assert.Contains("CompleteScheduleUpdateResponseAsync", source, StringComparison.Ordinal);
    }

    [Fact]
    public async Task Module_ShouldRouteDeleteSessionButtons()
    {
        var source = await ReadRepositoryFileAsync("src/GmRelay.DiscordBot/Features/Sessions/DiscordSessionInteractionModule.cs");

        Assert.Contains("[ComponentInteraction(\"delete_session\")]", source, StringComparison.Ordinal);
        Assert.Contains("DiscordDeleteSessionHandler", source, StringComparison.Ordinal);
    }

    [Fact]
    public async Task Module_ShouldRouteRsvpButtonsToNeutralHandler()
    {
        var source = await ReadRepositoryFileAsync("src/GmRelay.DiscordBot/Features/Sessions/DiscordSessionInteractionModule.cs");

        Assert.Contains("[ComponentInteraction(\"rsvp\")", source, StringComparison.Ordinal);
        Assert.Contains("HandleRsvpHandler", source, StringComparison.Ordinal);
        Assert.Contains("PlatformKind.Discord", source, StringComparison.Ordinal);
    }

    private static async Task<string> ReadRepositoryFileAsync(string relativePath)
    {
        var directory = new DirectoryInfo(AppContext.BaseDirectory);
        while (directory is not null)
        {
            var candidate = Path.Combine(directory.FullName, relativePath);
            if (File.Exists(candidate))
            {
                return await File.ReadAllTextAsync(candidate);
            }

            directory = directory.Parent;
        }

        throw new FileNotFoundException($"Could not locate repository file '{relativePath}'.");
    }
}
