using Ikar.Server.Data.Entities;
using Ikar.Shared;

namespace Ikar.Server.Tests;

public sealed class ChannelMembersControllerTests
{
    [Fact]
    public async Task AddMembers_CanAddBotAsChannelAdmin()
    {
        await using var database = new SqliteTestDatabase();
        await using var dbContext = await database.CreateContextAsync();
        var owner = CreateUser("owner");
        var bot = CreateUser("news_bot", isBot: true);
        var channel = CreateChannel(owner);
        dbContext.AddRange(owner, bot, channel);
        await dbContext.SaveChangesAsync();

        var controller = ControllerTestFixture.CreateChatsController(dbContext, owner.Id);
        var response = await controller.AddMembers(
            channel.Id,
            new AddChatMembersRequest([bot.Id], ChatMemberRole.Admin),
            CancellationToken.None);

        var details = ControllerTestFixture.ValueOf(response);
        var members = details.Members ?? throw new InvalidOperationException("Chat members were not returned.");
        var botMember = Assert.Single(members, member => member.User.Id == bot.Id);
        Assert.True(botMember.User.IsBot);
        Assert.Equal(ChatMemberRole.Admin, botMember.Role);
        Assert.True(botMember.Permissions.CanManageMembers);
        Assert.True(botMember.Permissions.CanPostMessages);
        Assert.True(botMember.Permissions.CanPinMessages);
        Assert.True(botMember.Permissions.CanDeleteMessages);
        Assert.True(botMember.Permissions.CanInviteUsers);
        Assert.Equal(2, details.SubscriberCount);
        Assert.Equal(2, details.AdminCount);
    }

    private static User CreateUser(string username, bool isBot = false) =>
        new()
        {
            Id = Guid.NewGuid(),
            Username = username,
            NormalizedUsername = username.ToUpperInvariant(),
            DisplayName = username,
            PasswordHash = "test",
            IsBot = isBot
        };

    private static Chat CreateChannel(User owner)
    {
        var channel = new Chat
        {
            Id = Guid.NewGuid(),
            Type = ChatType.Channel,
            Title = "News",
            Description = "Public news channel",
            PublicUsername = "news",
            CreatedById = owner.Id,
            CreatedBy = owner,
            CreatedAt = new DateTimeOffset(2026, 1, 1, 9, 0, 0, TimeSpan.Zero),
            LastActivityAt = new DateTimeOffset(2026, 1, 1, 9, 0, 0, TimeSpan.Zero)
        };
        channel.Members.Add(new ChatMember
        {
            ChatId = channel.Id,
            Chat = channel,
            UserId = owner.Id,
            User = owner,
            IsOwner = true,
            Role = ChatMemberRole.Owner,
            CanPinMessages = true,
            CanDeleteMessages = true,
            CanInviteUsers = true,
            CanPostMessages = true
        });

        return channel;
    }
}
