using FluentAssertions;
using foodmarket.Application.Inventory;
using Xunit;

namespace foodmarket.UnitTests;

/// <summary>Скользящее средневзвешенное себестоимости (логика SuppliesController.Post).</summary>
public class MovingAverageCostTests
{
    [Fact]
    public void First_supply_with_no_stock_uses_purchase_price()
    {
        // нет остатка, нет себестоимости → берём цену закупки
        MovingAverageCost.Compute(currentQty: 0m, currentCost: 0m, incomingQty: 10m, incomingUnitPrice: 100m)
            .Should().Be(100m);
    }

    [Fact]
    public void Weighted_average_of_old_and_new()
    {
        // 10 шт по 100 + 10 шт по 200 → среднее 150
        MovingAverageCost.Compute(currentQty: 10m, currentCost: 100m, incomingQty: 10m, incomingUnitPrice: 200m)
            .Should().Be(150m);
    }

    [Fact]
    public void Weighted_average_respects_quantities()
    {
        // 30 шт по 100 + 10 шт по 200 → (3000+2000)/40 = 125
        MovingAverageCost.Compute(currentQty: 30m, currentCost: 100m, incomingQty: 10m, incomingUnitPrice: 200m)
            .Should().Be(125m);
    }

    [Fact]
    public void Result_is_rounded_to_four_decimals()
    {
        // (1*1 + 2*2)/3 = 1.6666... → 1.6667
        MovingAverageCost.Compute(currentQty: 1m, currentCost: 1m, incomingQty: 2m, incomingUnitPrice: 2m)
            .Should().Be(1.6667m);
    }

    [Fact]
    public void Existing_stock_with_zero_cost_still_averages_when_qty_positive()
    {
        // currentCost==0 но currentQty>0 → НЕ берём цену закупки целиком,
        // считаем среднее: (5*0 + 5*200)/10 = 100
        MovingAverageCost.Compute(currentQty: 5m, currentCost: 0m, incomingQty: 5m, incomingUnitPrice: 200m)
            .Should().Be(100m);
    }

    [Fact]
    public void Zero_total_quantity_falls_back_to_purchase_price()
    {
        // возврат/сторно может дать totalQty==0 → не делим на ноль
        MovingAverageCost.Compute(currentQty: -10m, currentCost: 50m, incomingQty: 10m, incomingUnitPrice: 70m)
            .Should().Be(70m);
    }
}
