using Theriapolis.Core.Data;
using Theriapolis.Core.Entities;
using Theriapolis.Core.Tactical;
using Theriapolis.Core.Util;
using Xunit;

namespace Theriapolis.Tests.Entities;

public sealed class NpcActorTests
{
    private readonly ContentResolver _content = new(new ContentLoader(TestHelpers.DataDirectory));

    [Fact]
    public void Construct_AssignsHpAndAllegianceFromTemplate()
    {
        var t = _content.Npcs.Templates.First(x => x.Id == "wolf");
        var npc = new NpcActor(t);
        Assert.Equal(t.Hp, npc.CurrentHp);
        Assert.Equal(t.Hp, npc.MaxHp);
        Assert.Equal(Theriapolis.Core.Rules.Character.Allegiance.Hostile, npc.Allegiance);
        Assert.Equal("wild_animal", npc.BehaviorId);
        Assert.True(npc.IsAlive);
    }

    [Fact]
    public void IsAlive_FalseAtZeroHp()
    {
        var npc = new NpcActor(_content.Npcs.Templates.First(x => x.Id == "wolf"));
        npc.CurrentHp = 0;
        Assert.False(npc.IsAlive);
    }

    [Fact]
    public void ActorManager_SpawnNpc_GivesUniqueIdsAndTracksSource()
    {
        var mgr = new ActorManager();
        mgr.SpawnPlayer(new Vec2(0, 0));
        var t = _content.Npcs.Templates.First(x => x.Id == "wolf");
        var coord = new ChunkCoord(3, 4);
        var npc1 = mgr.SpawnNpc(t, new Vec2(10, 10), coord, sourceSpawnIndex: 0);
        var npc2 = mgr.SpawnNpc(t, new Vec2(11, 10), coord, sourceSpawnIndex: 1);
        Assert.NotEqual(npc1.Id, npc2.Id);
        Assert.Equal(2, mgr.Npcs.Count());
        Assert.Same(npc1, mgr.FindNpcBySource(coord, 0));
        Assert.Same(npc2, mgr.FindNpcBySource(coord, 1));
    }

    [Fact]
    public void ActorManager_RemoveActor_CleansUp()
    {
        var mgr = new ActorManager();
        var t = _content.Npcs.Templates.First(x => x.Id == "wolf");
        var npc = mgr.SpawnNpc(t, new Vec2(0, 0));
        Assert.True(mgr.RemoveActor(npc.Id));
        Assert.Empty(mgr.Npcs);
        Assert.False(mgr.RemoveActor(npc.Id));
    }
}
