// EN: Strategy for Physical products (Retail).
// VI: Strategy cho sản phẩm Physical (Bán lẻ).

using OrderService.Domain.AggregatesModel.OrderAggregate;
using OrderService.Domain.Strategies;
using OrderService.API.Infrastructure.HttpClients;

namespace OrderService.API.Application.Strategies;

/// <summary>
/// EN: Strategy for Physical products - routes to Inventory Service.
/// VI: Strategy cho sản phẩm Physical - route đến Inventory Service.
/// </summary>
public class RetailStrategy : ILineItemStrategy
{
    private readonly InventoryServiceClient _inventoryClient;
    private readonly ILogger<RetailStrategy> _logger;

    public string SupportedType => "Physical";

    public RetailStrategy(
        InventoryServiceClient inventoryClient,
        ILogger<RetailStrategy> logger)
    {
        _inventoryClient = inventoryClient ?? throw new ArgumentNullException(nameof(inventoryClient));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task<bool> ValidateAsync(
        OrderItem item,
        Guid shopId,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Validating Physical product / VI: Validate sản phẩm Physical: {ProductName}",
            item.ProductName);

        // EN: Check inventory availability
        // VI: Kiểm tra hàng tồn kho
        var isAvailable = await _inventoryClient.CheckStockAsync(
            item.ProductId,
            shopId,
            item.Quantity,
            cancellationToken);

        if (!isAvailable)
        {
            _logger.LogWarning(
                "EN: Insufficient stock / VI: Không đủ hàng: {ProductName}, Quantity: {Quantity}",
                item.ProductName,
                item.Quantity);
        }

        return isAvailable;
    }

    public async Task ExecuteAsync(
        OrderItem item,
        Guid shopId,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Executing Physical product / VI: Thực thi sản phẩm Physical: {ProductName}",
            item.ProductName);

        // EN: Deduct inventory
        // VI: Trừ hàng tồn kho
        var success = await _inventoryClient.DeductStockAsync(
            item.ProductId,
            shopId,
            item.Quantity,
            cancellationToken);

        if (!success)
        {
            throw new InvalidOperationException(
                $"EN: Failed to deduct stock / VI: Trừ kho thất bại: {item.ProductName}");
        }

        _logger.LogInformation(
            "EN: Stock deducted successfully / VI: Trừ kho thành công: {ProductName}",
            item.ProductName);
    }
}
