namespace GmRelay.Bot.Tests.Infrastructure.Telegram;

public sealed class TelegramPlatformMessengerSourceTests
{
    [Fact]
    public async Task Program_ShouldRegisterTelegramPlatformMessenger()
    {
        var program = await ReadRepositoryFileAsync("src/GmRelay.Bot/Program.cs");

        Assert.Contains("IPlatformMessenger", program, StringComparison.Ordinal);
        Assert.Contains("TelegramPlatformMessenger", program, StringComparison.Ordinal);
    }

    [Theory]
    [InlineData("src/GmRelay.Shared/Features/Sessions/CreateSession/JoinSessionHandler.cs")]
    [InlineData("src/GmRelay.Shared/Features/Sessions/CreateSession/LeaveSessionHandler.cs")]
    [InlineData("src/GmRelay.Bot/Features/Sessions/CreateSession/CancelSessionHandler.cs")]
    [InlineData("src/GmRelay.Bot/Features/Sessions/CreateSession/PromoteWaitlistedPlayerHandler.cs")]
    [InlineData("src/GmRelay.Bot/Features/Sessions/RescheduleSession/InitiateRescheduleHandler.cs")]
    [InlineData("src/GmRelay.Bot/Features/Sessions/RescheduleSession/HandleRescheduleTimeInputHandler.cs")]
    [InlineData("src/GmRelay.Bot/Features/Sessions/RescheduleSession/HandleRescheduleVoteHandler.cs")]
    [InlineData("src/GmRelay.Bot/Features/Sessions/RescheduleSession/RescheduleVotingDeadlineService.cs")]
    [InlineData("src/GmRelay.Bot/Features/Sessions/ExportCalendar/ExportCalendarHandler.cs", "src/GmRelay.Shared/Features/Sessions/ExportCalendar/ExportCalendarHandler.cs")]
    public async Task SessionFlows_ShouldUsePlatformMessengerForOutboundTelegramWork(string relativePath, string? sharedPath = null)
    {
        var source = await ReadRepositoryFileAsync(relativePath);
        var sharedSource = sharedPath is not null ? await ReadRepositoryFileAsync(sharedPath) : string.Empty;

        Assert.Contains("IPlatformMessenger", source + sharedSource, StringComparison.Ordinal);
        Assert.DoesNotContain("BatchMessageEditor.EditBatchMessageAsync", source, StringComparison.Ordinal);
        Assert.DoesNotContain(".AnswerCallbackQuery(", source, StringComparison.Ordinal);
    }

    [Fact]
    public async Task TelegramPlatformMessenger_ShouldOwnTelegramBotClientCalls()
    {
        var source = await ReadRepositoryFileAsync("src/GmRelay.Bot/Infrastructure/Telegram/TelegramPlatformMessenger.cs");

        Assert.Contains("ITelegramBotClient", source, StringComparison.Ordinal);
        Assert.Contains("BatchMessageEditor.EditBatchMessageAsync", source, StringComparison.Ordinal);
        Assert.Contains("AnswerCallbackQuery", source, StringComparison.Ordinal);
        Assert.Contains("SendDocument", source, StringComparison.Ordinal);
        Assert.Contains("SendConfirmationRequestAsync", source, StringComparison.Ordinal);
        Assert.Contains("UpdateConfirmationRequestAsync", source, StringComparison.Ordinal);
        Assert.Contains("SendJoinLinkNotificationAsync", source, StringComparison.Ordinal);
        Assert.Contains("SendDirectSessionNotificationAsync", source, StringComparison.Ordinal);
        Assert.Contains("UpdateRescheduleVoteAsync", source, StringComparison.Ordinal);
        Assert.Contains("messageThreadId", source, StringComparison.Ordinal);
        Assert.Contains("ParseMode.Html", source, StringComparison.Ordinal);
        Assert.Contains("InlineKeyboardButton.WithCallbackData", source, StringComparison.Ordinal);
    }

    [Fact]
    public async Task RescheduleVotingDeadlineService_ShouldUsePlatformMessengerForVoteMessageUpdates()
    {
        var source = await ReadRepositoryFileAsync(
            "src/GmRelay.Bot/Features/Sessions/RescheduleSession/RescheduleVotingDeadlineService.cs");

        Assert.DoesNotContain("ITelegramBotClient", source, StringComparison.Ordinal);
        Assert.DoesNotContain(".EditMessageText(", source, StringComparison.Ordinal);
        Assert.Contains("UpdateRescheduleVoteAsync", source, StringComparison.Ordinal);
        Assert.Contains("IPlatformMessenger", 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}'.");
    }
}
