using CartWise.Application.Services;
using CartWise.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;

namespace CartWise.Application.Tests;

public class HouseholdServiceTests : IDisposable
{
    private readonly CartWiseDbContext _db;
    private readonly HouseholdService _sut;

    public HouseholdServiceTests()
    {
        var options = new DbContextOptionsBuilder<CartWiseDbContext>()
            .UseInMemoryDatabase(Guid.NewGuid().ToString())
            .Options;

        _db = new CartWiseDbContext(options);
        _sut = new HouseholdService(_db, TimeProvider.System);
    }

    public void Dispose()
    {
        _db.Dispose();
        GC.SuppressFinalize(this);
    }

    [Fact]
    public async Task CreateHouseholdAsync_CreatesHouseholdWithOwnerMembership()
    {
        var result = await _sut.CreateHouseholdAsync("The Smiths", "user-1");

        Assert.True(result.IsSuccess);
        Assert.Equal("The Smiths", result.Value!.Name);
        Assert.True(await _sut.IsMemberAsync(result.Value.HouseholdId, "user-1"));
    }

    [Fact]
    public async Task CreateHouseholdAsync_FailsWhenUserAlreadyBelongsToAHousehold()
    {
        await _sut.CreateHouseholdAsync("The Smiths", "user-1");

        var result = await _sut.CreateHouseholdAsync("Second Household", "user-1");

        Assert.False(result.IsSuccess);
        Assert.NotNull(result.Error);
    }

    [Fact]
    public async Task CreateHouseholdAsync_FailsWhenNameIsMissing()
    {
        var result = await _sut.CreateHouseholdAsync("   ", "user-1");

        Assert.False(result.IsSuccess);
    }

    [Fact]
    public async Task GetCurrentHouseholdAsync_ReturnsNullWhenUserHasNoHousehold()
    {
        var household = await _sut.GetCurrentHouseholdAsync("user-1");

        Assert.Null(household);
    }

    [Fact]
    public async Task GetCurrentHouseholdAsync_ReturnsHouseholdForMember()
    {
        var created = await _sut.CreateHouseholdAsync("The Smiths", "user-1");

        var household = await _sut.GetCurrentHouseholdAsync("user-1");

        Assert.NotNull(household);
        Assert.Equal(created.Value!.HouseholdId, household!.HouseholdId);
    }

    [Fact]
    public async Task IsMemberAsync_ReturnsFalseForNonMember()
    {
        var created = await _sut.CreateHouseholdAsync("The Smiths", "user-1");

        Assert.False(await _sut.IsMemberAsync(created.Value!.HouseholdId, "user-2"));
    }
}
