using RpgRoller.Components.Pages;

namespace RpgRoller.Tests;

public sealed class WorkspaceStateTests
{
    [Fact]
    public void OwnerLabel_ResolvesCurrentUserGmAndFallbacks()
    {
        var gmId = Guid.NewGuid();
        var userId = Guid.NewGuid();
        var otherOwnerId = Guid.NewGuid();
        var state = new WorkspaceState
        {
            User = new(userId, "user", "User", []),
            SelectedCampaign = new(Guid.NewGuid(), "Alpha", "d6", new(gmId, "GM"), [
                new(Guid.NewGuid(), "Scout", otherOwnerId, Guid.NewGuid(), "Other Owner")
            ])
        };

        Assert.Equal("You", state.OwnerLabel(userId));
        Assert.Equal("GM (GM)", state.OwnerLabel(gmId));
        Assert.Equal("Other Owner", state.OwnerLabel(otherOwnerId));
        Assert.Equal("Unknown owner", state.OwnerLabel(Guid.NewGuid()));
    }

    [Fact]
    public void SkillDefinitionLabel_FormatsD6RolemasterAndDefaultRulesets()
    {
        var skill = new CharacterSheetSkill(Guid.NewGuid(), null, "Awareness", "d100!+15", 1, true, 5, true);
        var state = new WorkspaceState
            { SelectedCampaign = new(Guid.NewGuid(), "Alpha", "d6", new(Guid.NewGuid(), "GM"), []) };

        Assert.Equal("d100!+15, wild 1, fumble on", state.SkillDefinitionLabel(skill));

        state.SelectedCampaign = new(Guid.NewGuid(), "Alpha", "rolemaster", new(Guid.NewGuid(), "GM"), []);
        Assert.Equal("Open-ended percentile: d100!+15, fumble <= 5, auto retry", state.SkillDefinitionLabel(skill));

        state.SelectedCampaign = new(Guid.NewGuid(), "Alpha", "dnd5e", new(Guid.NewGuid(), "GM"), []);
        Assert.Equal("d100!+15", state.SkillDefinitionLabel(skill));
    }

    [Fact]
    public void PlaySelections_ForNonGm_FilterToOwnedCharactersAndPreferSelectedThenActive()
    {
        var userId = Guid.NewGuid();
        var ownedCharacter = new CharacterSummary(Guid.NewGuid(), "Owned", userId, Guid.NewGuid(), "User");
        var secondOwnedCharacter = new CharacterSummary(Guid.NewGuid(), "Owned Two", userId, Guid.NewGuid(), "User");
        var otherCharacter = new CharacterSummary(Guid.NewGuid(), "Other", Guid.NewGuid(), Guid.NewGuid(), "Other");
        var state = new WorkspaceState
        {
            User = new(userId, "user", "User", []),
            SelectedCampaign = new(Guid.NewGuid(), "Alpha", "d6", new(Guid.NewGuid(), "GM"),
                [ownedCharacter, secondOwnedCharacter, otherCharacter]),
            SelectedCharacterId = secondOwnedCharacter.Id,
            ActiveCharacterId = ownedCharacter.Id,
            SelectedCharacterSkills = [new(Guid.NewGuid(), null, "Stealth", "2D+1", 1, true, null, false)],
            SelectedCharacterSkillGroups = [new(Guid.NewGuid(), "Combat", "2D+1", 1, true, null)]
        };

        Assert.Equal(2, state.PlaySelectedCampaign!.Characters.Length);
        Assert.Equal(secondOwnedCharacter.Id, state.PlaySelectedCharacterId);
        Assert.Single(state.PlaySelectedCharacterSkills);
        Assert.Single(state.PlaySelectedCharacterSkillGroups);

        state.SelectedCharacterId = Guid.NewGuid();
        Assert.Equal(ownedCharacter.Id, state.PlaySelectedCharacterId);

        state.ActiveCharacterId = Guid.NewGuid();
        Assert.Equal(ownedCharacter.Id, state.PlaySelectedCharacterId);
    }

    [Fact]
    public void PlaySelections_ForGm_ExposeEntireCampaignAndKeepNonOwnedSelection()
    {
        var gmId = Guid.NewGuid();
        var otherCharacter = new CharacterSummary(Guid.NewGuid(), "Other", Guid.NewGuid(), Guid.NewGuid(), "Other");
        var ownedCharacter = new CharacterSummary(Guid.NewGuid(), "Owned", gmId, Guid.NewGuid(), "GM");
        var state = new WorkspaceState
        {
            User = new(gmId, "gm", "GM", []),
            SelectedCampaign = new(Guid.NewGuid(), "Alpha", "d6", new(gmId, "GM"),
                [ownedCharacter, otherCharacter]),
            SelectedCharacterId = otherCharacter.Id
        };

        Assert.Equal(2, state.PlaySelectedCampaign!.Characters.Length);
        Assert.Equal(otherCharacter.Id, state.PlaySelectedCharacterId);
        Assert.Equal(otherCharacter.Id, state.PlaySelectedCharacter!.Id);
    }

    [Fact]
    public void CampaignAndConnectionFlags_ReflectCurrentState()
    {
        var adminId = Guid.NewGuid();
        var state = new WorkspaceState
        {
            User = new(adminId, "admin", "Admin", [UserRoles.Admin]),
            SelectedCampaign = new(Guid.NewGuid(), "Alpha", "d6", new(adminId, "Admin"), []),
            ConnectionState = "reconnecting"
        };

        Assert.True(state.IsCurrentUserAdmin);
        Assert.True(state.IsCurrentUserGm);
        Assert.True(state.CanDeleteSelectedCampaign);
        Assert.True(state.IsSelectedCampaignD6);
        Assert.Equal("Reconnecting", state.ConnectionStateLabel);
        Assert.Equal("warn", state.ConnectionStateCssClass);

        state.ConnectionState = "connected";

        Assert.Equal("Connected", state.ConnectionStateLabel);
        Assert.Equal("ok", state.ConnectionStateCssClass);
    }
}