using ZB.MOM.WW.CBDD.Core.Indexing;

namespace ZB.MOM.WW.CBDD.Tests;

public class VectorMathTests
{
    [Fact]
    public void Distance_Should_Cover_All_Metrics()
    {
        float[] v1 = [1f, 2f];
        float[] v2 = [3f, 4f];

        var cosineDistance = VectorMath.Distance(v1, v2, VectorMetric.Cosine);
        var l2Distance = VectorMath.Distance(v1, v2, VectorMetric.L2);
        var dotDistance = VectorMath.Distance(v1, v2, VectorMetric.DotProduct);

        l2Distance.ShouldBe(8f);
        dotDistance.ShouldBe(-11f);

        var expectedCosine = 1f - (11f / (MathF.Sqrt(5f) * 5f));
        MathF.Abs(cosineDistance - expectedCosine).ShouldBeLessThan(0.0001f);
    }

    [Fact]
    public void CosineSimilarity_Should_Return_Zero_For_ZeroMagnitude_Vector()
    {
        float[] v1 = [0f, 0f, 0f];
        float[] v2 = [1f, 2f, 3f];

        VectorMath.CosineSimilarity(v1, v2).ShouldBe(0f);
    }

    [Fact]
    public void DotProduct_Should_Throw_For_Length_Mismatch()
    {
        float[] v1 = [1f, 2f];
        float[] v2 = [1f];

        Should.Throw<ArgumentException>(() => VectorMath.DotProduct(v1, v2));
    }

    [Fact]
    public void EuclideanDistanceSquared_Should_Throw_For_Length_Mismatch()
    {
        float[] v1 = [1f, 2f, 3f];
        float[] v2 = [1f, 2f];

        Should.Throw<ArgumentException>(() => VectorMath.EuclideanDistanceSquared(v1, v2));
    }
}
