using Kompas.Mcp.Core.Documents;
using Kompas.Mcp.Core.Modeling;
using Kompas.Mcp.Core.Query;

namespace Kompas.Mcp.Tests.Integration;

/// <summary>Интеграция: массово-центровочные характеристики (get_part_info).</summary>
[Trait("Category", "Integration")]
[Collection(KompasCollection.Name)]
public sealed class QueryTests : IntegrationTestBase
{
    private readonly DocumentService _docs;
    private readonly PartModeler _modeler;
    private readonly QueryService _query;

    public QueryTests(KompasFixture fx) : base(fx)
    {
        _docs = new DocumentService(fx.Session, fx.Dispatcher);
        _modeler = new PartModeler(fx.Session, fx.Dispatcher);
        _query = new QueryService(fx.Session, fx.Dispatcher);
    }

    [Fact]
    public async Task Cylinder_volume_matches_formula()
    {
        await _docs.CreateAsync(KompasDocumentType.Part);
        try
        {
            // Цилиндр R10 × H20 на XOY: объём = π·R²·H = π·100·20 ≈ 6283.19 мм³.
            var s = await _modeler.OpenSketchAsync(BasePlane.XOY);
            await _modeler.AddCircleAsync(s, 0, 0, 10);
            await _modeler.CloseSketchAsync(s);
            var boss = await _modeler.ExtrudeAsync(s, depth: 20);
            Assert.True(boss > 0);
            await _modeler.RebuildAsync();

            var info = await _query.GetPartInfoAsync();

            // Единицы детерминированы сервисом: мм³, мм², кг, мм.
            var expectedVolume = Math.PI * 100 * 20; // ≈ 6283.19 мм³
            Assert.InRange(info.Volume, expectedVolume * 0.99, expectedVolume * 1.01);

            // Центр масс цилиндра — на оси, по высоте посередине (Z = H/2 = 10 мм).
            Assert.InRange(info.CenterX, -0.1, 0.1);
            Assert.InRange(info.CenterY, -0.1, 0.1);
            Assert.InRange(info.CenterZ, 9.9, 10.1);

            // Площадь поверхности: 2·π·R² (торцы) + 2·π·R·H (бок) = 2π·100 + 2π·10·20 ≈ 1884.96 мм².
            var expectedArea = 2 * Math.PI * 100 + 2 * Math.PI * 10 * 20;
            Assert.InRange(info.Area, expectedArea * 0.98, expectedArea * 1.02);

            // Масса стального цилиндра (плотность ≈ 7.856 г/см³): V[см³]·ρ ≈ 6.283·7.856 ≈ 49.36 г = 0.0494 кг.
            Assert.InRange(info.Mass, 0.045, 0.055);

            // Габарит цилиндра R10×H20 на XOY: X,Y ∈ [-10;10], Z ∈ [0;20].
            var bb = await _query.GetBoundingBoxAsync();
            Assert.InRange(bb.MinX, -10.1, -9.9);
            Assert.InRange(bb.MaxX, 9.9, 10.1);
            Assert.InRange(bb.MinZ, -0.1, 0.1);
            Assert.InRange(bb.MaxZ, 19.9, 20.1);
            Assert.InRange(bb.SizeZ, 19.9, 20.1);
        }
        finally
        {
            await _docs.CloseAsync(save: false);
        }
    }
}
