using CartWise.Domain.Entities;
using CartWise.Domain.Enums;

namespace CartWise.Domain.Tests;

public class ShoppingListTests
{
    private static readonly DateTime Now = new(2026, 8, 10, 12, 0, 0, DateTimeKind.Utc);

    [Fact]
    public void Constructor_CreatesActiveListWithNoItems()
    {
        var list = new ShoppingList(Guid.NewGuid(), "Groceries", "user-1", Now);

        Assert.Equal(ShoppingListStatus.Active, list.Status);
        Assert.Empty(list.Items);
    }

    [Theory]
    [InlineData("")]
    [InlineData("   ")]
    [InlineData(null)]
    public void Constructor_ThrowsWhenNameIsMissing(string? name)
    {
        Assert.Throws<ArgumentException>(() => new ShoppingList(Guid.NewGuid(), name!, "user-1", Now));
    }

    [Fact]
    public void Constructor_ThrowsWhenHouseholdIdIsEmpty()
    {
        Assert.Throws<ArgumentException>(() => new ShoppingList(Guid.Empty, "Groceries", "user-1", Now));
    }

    [Fact]
    public void AddItem_AddsItemWithNeededStatusAndZeroSortOrder()
    {
        var list = new ShoppingList(Guid.NewGuid(), "Groceries", "user-1", Now);

        var item = list.AddItem("Milk", 2m, "gal", "user-1", Now);

        Assert.Single(list.Items);
        Assert.Equal("Milk", item.DisplayName);
        Assert.Equal(ShoppingListItemStatus.Needed, item.Status);
        Assert.Equal(0, item.SortOrder);
        Assert.Equal(list.ShoppingListId, item.ShoppingListId);
    }

    [Fact]
    public void AddItem_AssignsIncrementingSortOrder()
    {
        var list = new ShoppingList(Guid.NewGuid(), "Groceries", "user-1", Now);

        var first = list.AddItem("Milk", null, null, "user-1", Now);
        var second = list.AddItem("Bread", null, null, "user-1", Now);

        Assert.Equal(0, first.SortOrder);
        Assert.Equal(1, second.SortOrder);
    }

    [Fact]
    public void AddItem_DoesNotRequireQuantityOrUnit()
    {
        var list = new ShoppingList(Guid.NewGuid(), "Groceries", "user-1", Now);

        var item = list.AddItem("Milk", null, null, "user-1", Now);

        Assert.Null(item.Quantity);
        Assert.Null(item.Unit);
    }

    [Theory]
    [InlineData("")]
    [InlineData("   ")]
    [InlineData(null)]
    public void AddItem_ThrowsWhenDisplayNameIsMissing(string? displayName)
    {
        var list = new ShoppingList(Guid.NewGuid(), "Groceries", "user-1", Now);

        Assert.Throws<ArgumentException>(() => list.AddItem(displayName!, null, null, "user-1", Now));
    }
}
