// EN: Factory for resolving line item strategies.
// VI: Factory để resolve line item strategies.

using OrderService.Domain.Strategies;

namespace OrderService.API.Application.Strategies;

/// <summary>
/// EN: Factory for getting the appropriate strategy based on product type.
/// VI: Factory lấy strategy phù hợp dựa trên loại sản phẩm.
/// </summary>
public class StrategyFactory
{
    private readonly IEnumerable<ILineItemStrategy> _strategies;
    private readonly ILogger<StrategyFactory> _logger;

    public StrategyFactory(
        IEnumerable<ILineItemStrategy> strategies,
        ILogger<StrategyFactory> logger)
    {
        _strategies = strategies ?? throw new ArgumentNullException(nameof(strategies));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    /// <summary>
    /// EN: Get strategy by product type.
    /// VI: Lấy strategy theo loại sản phẩm.
    /// </summary>
    public ILineItemStrategy GetStrategy(string productType)
    {
        _logger.LogDebug(
            "EN: Getting strategy for product type / VI: Lấy strategy cho loại sản phẩm: {ProductType}",
            productType);

        var strategy = _strategies.FirstOrDefault(s => s.SupportedType.Equals(productType, StringComparison.OrdinalIgnoreCase));

        if (strategy == null)
        {
            var availableTypes = string.Join(", ", _strategies.Select(s => s.SupportedType));
            throw new InvalidOperationException(
                $"EN: No strategy found for product type: {productType}. Available types: {availableTypes} / " +
                $"VI: Không tìm thấy strategy cho loại sản phẩm: {productType}. Các loại có sẵn: {availableTypes}");
        }

        return strategy;
    }

    /// <summary>
    /// EN: Get all available product types.
    /// VI: Lấy tất cả loại sản phẩm có sẵn.
    /// </summary>
    public IEnumerable<string> GetAvailableTypes()
    {
        return _strategies.Select(s => s.SupportedType);
    }
}
