namespace RpgRoller.Tests;

public sealed class ServiceStateInfrastructureTests
{
    [Fact]
    public void GameStateStore_StartsWithEmptyMutableCollections()
    {
        var store = new GameStateStore();

        Assert.NotNull(store.Gate);
        Assert.Empty(store.UsersById);
        Assert.Empty(store.UserIdsByUsername);
        Assert.Empty(store.SessionsByToken);
        Assert.Empty(store.CampaignsById);
        Assert.Empty(store.CampaignStateById);
        Assert.Empty(store.CharactersById);
        Assert.Empty(store.SkillGroupsById);
        Assert.Empty(store.SkillsById);
        Assert.Empty(store.RollLog);
    }

    [Fact]
    public void GameStateCloneFactory_ProducesDetachedCopies()
    {
        var user = new UserAccount
        {
            Id = Guid.NewGuid(),
            Username = "user",
            UsernameNormalized = "USER",
            PasswordHash = "hash",
            DisplayName = "User",
            Roles = "admin",
            ActiveCharacterId = Guid.NewGuid()
        };
        var session = new UserSession
        {
            Token = "token",
            UserId = user.Id,
            CreatedAtUtc = DateTimeOffset.UtcNow
        };
        var campaign = new Campaign
        {
            Id = Guid.NewGuid(),
            GmUserId = user.Id,
            Name = "Main",
            Ruleset = RulesetKind.D6,
            Version = 3
        };
        var character = new Character
        {
            Id = Guid.NewGuid(),
            OwnerUserId = user.Id,
            CampaignId = campaign.Id,
            Name = "Hero"
        };
        var skillGroup = new SkillGroup
        {
            Id = Guid.NewGuid(),
            CharacterId = character.Id,
            Name = "Group",
            DiceRollDefinition = "2D+1",
            WildDice = 1,
            AllowFumble = true,
            FumbleRange = null
        };
        var skill = new Skill
        {
            Id = Guid.NewGuid(),
            CharacterId = character.Id,
            SkillGroupId = skillGroup.Id,
            Name = "Skill",
            DiceRollDefinition = "2D+2",
            WildDice = 1,
            AllowFumble = true,
            FumbleRange = null
        };
        var logEntry = new RollLogEntry
        {
            Id = Guid.NewGuid(),
            CampaignId = campaign.Id,
            CharacterId = character.Id,
            SkillId = skill.Id,
            RollerUserId = user.Id,
            Visibility = RollVisibility.Public,
            Result = 12,
            Breakdown = "6 + 6 = 12",
            Dice = "[]",
            TimestampUtc = DateTimeOffset.UtcNow
        };

        Assert.NotSame(user, GameStateCloneFactory.CloneUser(user));
        Assert.NotSame(session, GameStateCloneFactory.CloneSession(session));
        Assert.NotSame(campaign, GameStateCloneFactory.CloneCampaign(campaign));
        Assert.NotSame(character, GameStateCloneFactory.CloneCharacter(character));
        Assert.NotSame(skillGroup, GameStateCloneFactory.CloneSkillGroup(skillGroup));
        Assert.NotSame(skill, GameStateCloneFactory.CloneSkill(skill));
        Assert.NotSame(logEntry, GameStateCloneFactory.CloneRollLogEntry(logEntry));
    }
}