using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using NeonSprawl.Server.Game.Gigs;
using Xunit;

namespace NeonSprawl.Server.Tests.Game.Gigs;

/// <summary>NEO-44: combat defeat hook → <c>breach</c> gig XP via dedicated store (not E2.M2).</summary>
public sealed class CombatDefeatGigXpGrantTests
{
    [Fact]
    public async Task GrantOnCombatDefeat_WhenPlayerKnown_ShouldIncreaseBreachXp()
    {
        // Arrange
        await using var factory = new InMemoryWebApplicationFactory();
        _ = factory.CreateClient();
        using var scope = factory.Services.CreateScope();
        var gigStore = scope.ServiceProvider.GetRequiredService<IPlayerGigProgressionStore>();

        // Act
        CombatDefeatGigXpGrant.GrantOnCombatDefeat("dev-local-1", gigStore);

        // Assert
        var totals = gigStore.GetXpTotals("dev-local-1");
        Assert.True(totals.TryGetValue(GigProgressionConstants.PrototypeMainGigId, out var xp));
        Assert.Equal(GigProgressionConstants.CombatDefeatXpAmount, xp);
    }

    [Fact]
    public async Task GrantOnCombatDefeat_WhenPlayerUnknown_ShouldNotThrow()
    {
        // Arrange
        await using var factory = new InMemoryWebApplicationFactory();
        _ = factory.CreateClient();
        using var scope = factory.Services.CreateScope();
        var gigStore = scope.ServiceProvider.GetRequiredService<IPlayerGigProgressionStore>();

        // Act
        var exception = Record.Exception(() =>
            CombatDefeatGigXpGrant.GrantOnCombatDefeat("missing-player", gigStore));

        // Assert
        Assert.Null(exception);
        Assert.Empty(gigStore.GetXpTotals("missing-player"));
    }

    [Fact]
    public async Task GrantOnCombatDefeat_WhenPlayerUnknown_ShouldNotThrow_WithLogger()
    {
        // Arrange
        await using var factory = new InMemoryWebApplicationFactory();
        _ = factory.CreateClient();
        using var scope = factory.Services.CreateScope();
        var gigStore = scope.ServiceProvider.GetRequiredService<IPlayerGigProgressionStore>();
        var logger = scope.ServiceProvider.GetRequiredService<ILoggerFactory>()
            .CreateLogger(nameof(CombatDefeatGigXpGrant));

        // Act
        var exception = Record.Exception(() =>
            CombatDefeatGigXpGrant.GrantOnCombatDefeat("missing-player", gigStore, logger));

        // Assert
        Assert.Null(exception);
    }
}
