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

namespace Kompas.Mcp.Tests.Integration;

/// <summary>Интеграция: рассечение тела, перемещение тела, объединение (cut→spread→union).</summary>
[Trait("Category", "Integration")]
[Collection(KompasCollection.Name)]
public sealed class SolidEditTests : IntegrationTestBase
{
    private readonly DocumentService _docs;
    private readonly PartModeler _modeler;
    private readonly SolidEditService _solid;
    private readonly FaceEditService _face;
    private readonly QueryService _query;
    private readonly ValidationService _validation;

    public SolidEditTests(KompasFixture fx) : base(fx)
    {
        _docs = new DocumentService(fx.Session, fx.Dispatcher);
        _modeler = new PartModeler(fx.Session, fx.Dispatcher);
        _solid = new SolidEditService(fx.Session, fx.Dispatcher);
        _face = new FaceEditService(fx.Session, fx.Dispatcher);
        _query = new QueryService(fx.Session, fx.Dispatcher);
        _validation = new ValidationService(fx.Session, fx.Dispatcher);
    }

    [Fact]
    public async Task Split_move_bridge_union_grows_height_cleanly()
    {
        await _docs.CreateAsync(KompasDocumentType.Part);
        try
        {
            // Брусок 20×20×10 на XOY: Z[0;10].
            var s = await _modeler.OpenSketchAsync(BasePlane.XOY);
            await _modeler.AddRectangleAsync(s, 0, 0, 20, 20);
            await _modeler.CloseSketchAsync(s);
            await _modeler.ExtrudeAsync(s, depth: 10);
            await _modeler.RebuildAsync();

            // 1) Рассечь по XOY на Z=5 → 2 тела.
            var bodies = await _solid.SplitByPlaneAsync(BasePlane.XOY, offset: 5);
            Assert.Equal(2, bodies.Count);

            // 2) Сдвинуть верхнее тело (max Z) на +2 по Z.
            var upper = bodies.OrderByDescending(b => b.MaxZ).First();
            await _solid.MoveBodyAsync(upper.Index, dz: 2);

            // 3) Мост: толкнуть грань реза нижнего тела (центр (10,10,5)) на +2 вверх до стыка.
            await _face.MoveFaceAsync(10, 10, 5, distance: 2);

            // 4) Объединить тела в одно.
            await _solid.UnionAllAsync();
            await _modeler.RebuildAsync();

            // Итог: высота 10 → 12, единое тело, построение чистое.
            var bb = await _query.GetBoundingBoxAsync();
            Assert.InRange(bb.SizeZ, 11.9, 12.1);
            Assert.Empty(await _validation.ValidatePartAsync());
        }
        finally
        {
            await _docs.CloseAsync(save: false);
        }
    }
}
