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

namespace Kompas.Mcp.Tests.Integration;

/// <summary>
/// Интеграция: имя операции в дереве построения. Без имени дерево — «Эскиз:1», «Элемент
/// выдавливания:1», и вернувшийся к модели агент (или человек) не знает, что чем построено.
/// Имя ставится ДО Create()/Update() и должно читаться обратно через дерево (list_features).
/// </summary>
[Trait("Category", "Integration")]
[Collection(KompasCollection.Name)]
public sealed class FeatureNamingTests : IntegrationTestBase
{
    private readonly DocumentService _docs;
    private readonly PartModeler _modeler;
    private readonly PrimitiveService _primitives;
    private readonly ModelInspectionService _inspection;

    public FeatureNamingTests(KompasFixture fx) : base(fx)
    {
        _docs = new DocumentService(fx.Session, fx.Dispatcher);
        _modeler = new PartModeler(fx.Session, fx.Dispatcher);
        _primitives = new PrimitiveService(fx.Session, fx.Dispatcher);
        _inspection = new ModelInspectionService(fx.Session, fx.Dispatcher);
    }

    private async Task<IReadOnlyList<string>> TreeNamesAsync()
        => (await _inspection.DescribeModelAsync(InspectionText.ModelSections.Tree))
            .Features.Select(f => f.Name).ToList();

    [Fact]
    public async Task Sketch_and_extrusion_carry_their_names_into_the_tree()
    {
        await _docs.CreateAsync(KompasDocumentType.Part);
        try
        {
            var s = await _modeler.OpenSketchAsync(BasePlane.XOY, name: "Контур плашки");
            await _modeler.AddRectangleAsync(s, 0, 0, 20, 10);
            await _modeler.CloseSketchAsync(s);
            await _modeler.ExtrudeAsync(s, depth: 3, name: "Плашка 20×10×3");
            await _modeler.RebuildAsync();

            var names = await TreeNamesAsync();
            Assert.Contains("Контур плашки", names);
            Assert.Contains("Плашка 20×10×3", names);
        }
        finally { await _docs.CloseAsync(save: false); }
    }

    [Fact]
    public async Task Primitive_carries_its_name_into_the_tree()
    {
        await _docs.CreateAsync(KompasDocumentType.Part);
        try
        {
            await _primitives.PrimitiveAsync(PrimitiveKind.Block, 0, 0, 0,
                length: 20, width: 10, height: 3, name: "Основание корпуса");

            var names = await TreeNamesAsync();
            Assert.Contains("Основание корпуса", names);
        }
        finally { await _docs.CloseAsync(save: false); }
    }

    [Fact]
    public async Task Without_a_name_kompas_keeps_its_own()
    {
        await _docs.CreateAsync(KompasDocumentType.Part);
        try
        {
            var s = await _modeler.OpenSketchAsync(BasePlane.XOY);
            await _modeler.AddRectangleAsync(s, 0, 0, 20, 10);
            await _modeler.CloseSketchAsync(s);
            await _modeler.ExtrudeAsync(s, depth: 3);
            await _modeler.RebuildAsync();

            // Имя не задано — дерево остаётся с системными именами, но узлы на месте.
            var names = await TreeNamesAsync();
            Assert.NotEmpty(names);
            Assert.All(names, n => Assert.False(string.IsNullOrWhiteSpace(n)));
        }
        finally { await _docs.CloseAsync(save: false); }
    }
}
