using FluentAssertions;
using MerchantService.Domain.AggregatesModel.ShopAggregate;
using MerchantService.Domain.SeedWork;
using Xunit;

namespace MerchantService.UnitTests.Domain;

/// <summary>
/// EN: Unit tests for ShopFeatures value object — validates ForCategory() mapping for all verticals.
/// VI: Unit tests cho value object ShopFeatures — kiểm tra mapping ForCategory() cho tất cả ngành hàng.
/// </summary>
public class ShopFeaturesTests
{
    // ──────── HELPER ────────

    private static BusinessCategory Cat(int id) => Enumeration.FromValue<BusinessCategory>(id);

    // ──────── F&B VERTICALS ────────

    [Theory]
    [InlineData(1)]  // FoodBeverage
    [InlineData(11)] // Cafe
    [InlineData(12)] // Restaurant
    public void ForCategory_FnBVerticals_ShouldHaveTablesKitchenInventoryDelivery(int categoryId)
    {
        // Act
        var features = ShopFeatures.ForCategory(Cat(categoryId));

        // Assert
        features.HasInventory.Should().BeTrue($"Category {categoryId} should have Inventory");
        features.HasTables.Should().BeTrue($"Category {categoryId} should have Tables");
        features.HasKitchen.Should().BeTrue($"Category {categoryId} should have Kitchen");
        features.HasDelivery.Should().BeTrue($"Category {categoryId} should have Delivery");
        features.HasBooking.Should().BeFalse($"Category {categoryId} should not have Booking");
        features.HasShipping.Should().BeFalse($"Category {categoryId} should not have Shipping");
    }

    // ──────── RETAIL VERTICALS ────────

    [Theory]
    [InlineData(2)]  // Fashion
    [InlineData(3)]  // Electronics
    [InlineData(9)]  // Grocery
    [InlineData(10)] // HomeFurniture
    public void ForCategory_RetailVerticals_ShouldHaveInventoryAndShipping(int categoryId)
    {
        // Act
        var features = ShopFeatures.ForCategory(Cat(categoryId));

        // Assert
        features.HasInventory.Should().BeTrue();
        features.HasShipping.Should().BeTrue();
        features.HasTables.Should().BeFalse();
        features.HasKitchen.Should().BeFalse();
        features.HasBooking.Should().BeFalse();
    }

    // ──────── SERVICE VERTICALS ────────

    [Theory]
    [InlineData(4)] // Healthcare
    [InlineData(6)] // Education
    [InlineData(8)] // Services
    public void ForCategory_ServiceVerticals_ShouldHaveBookingOnly(int categoryId)
    {
        // Act
        var features = ShopFeatures.ForCategory(Cat(categoryId));

        // Assert
        features.HasBooking.Should().BeTrue();
        features.HasInventory.Should().BeFalse();
        features.HasTables.Should().BeFalse();
    }

    // ──────── BEAUTY (SPECIAL CASE) ────────

    [Fact]
    public void ForCategory_Beauty_ShouldHaveBookingAndInventory()
    {
        // Act
        var features = ShopFeatures.ForCategory(BusinessCategory.Beauty);

        // Assert
        features.HasBooking.Should().BeTrue();
        features.HasInventory.Should().BeTrue("Beauty clinics sell products");
        features.HasTables.Should().BeFalse();
        features.HasKitchen.Should().BeFalse();
    }

    // ──────── ENTERTAINMENT VERTICALS ────────

    [Theory]
    [InlineData(7)]  // Entertainment
    [InlineData(13)] // Karaoke
    public void ForCategory_EntertainmentVerticals_ShouldHaveBookingAndInventory(int categoryId)
    {
        // Act
        var features = ShopFeatures.ForCategory(Cat(categoryId));

        // Assert
        features.HasBooking.Should().BeTrue();
        features.HasInventory.Should().BeTrue();
    }

    // ──────── SPA ────────

    [Fact]
    public void ForCategory_Spa_ShouldHaveBookingOnly()
    {
        // Act
        var features = ShopFeatures.ForCategory(BusinessCategory.Spa);

        // Assert
        features.HasBooking.Should().BeTrue();
        features.HasInventory.Should().BeFalse("Spa focuses on services, not products");
        features.HasTables.Should().BeFalse();
    }

    // ──────── DEFAULT (OTHER) ────────

    [Fact]
    public void ForCategory_OtherCategory_ShouldHaveInventoryAndBooking()
    {
        // Act
        var features = ShopFeatures.ForCategory(BusinessCategory.Other);

        // Assert
        features.HasInventory.Should().BeTrue();
        features.HasBooking.Should().BeTrue();
    }

    // ──────── VALUE OBJECT TESTS ────────

    [Fact]
    public void Empty_ShouldReturnAllFlagsDisabled()
    {
        // Act
        var features = ShopFeatures.Empty;

        // Assert
        features.HasInventory.Should().BeFalse();
        features.HasBooking.Should().BeFalse();
        features.HasTables.Should().BeFalse();
        features.HasKitchen.Should().BeFalse();
        features.HasShipping.Should().BeFalse();
        features.HasDelivery.Should().BeFalse();
    }
}
