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

namespace Kompas.Mcp.Tests.Integration;

/// <summary>Интеграция: импорт/экспорт STEP и обход компонентов сборки.</summary>
[Trait("Category", "Integration")]
[Collection(KompasCollection.Name)]
public sealed class ConversionTests : IntegrationTestBase
{
    private readonly DocumentService _docs;
    private readonly PartModeler _modeler;
    private readonly ConversionService _conv;
    private readonly QueryService _query;

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

    private async Task BuildBoxAsync(double w, double d, double h)
    {
        var s = await _modeler.OpenSketchAsync(BasePlane.XOY);
        await _modeler.AddRectangleAsync(s, 0, 0, w, d);
        await _modeler.CloseSketchAsync(s);
        await _modeler.ExtrudeAsync(s, depth: h);
        await _modeler.RebuildAsync();
    }

    [Fact]
    public async Task Exports_active_part_to_step_file()
    {
        await _docs.CreateAsync(KompasDocumentType.Part);
        try
        {
            await BuildBoxAsync(30, 20, 10);
            var path = TestPaths.NewFile(".step");

            await _conv.ExportStepAsync(path, StepFormat.Ap214);

            Assert.True(File.Exists(path), "STEP-файл не создан.");
            Assert.True(new FileInfo(path).Length > 0, "STEP-файл пуст.");
        }
        finally
        {
            await _docs.CloseAsync(save: false);
        }
    }

    [Fact]
    public async Task Imports_step_back_with_geometry()
    {
        // arrange: построить брусок и экспортировать в STEP
        await _docs.CreateAsync(KompasDocumentType.Part);
        string path = TestPaths.NewFile(".step");
        try
        {
            await BuildBoxAsync(40, 30, 10);
            await _conv.ExportStepAsync(path, StepFormat.Auto);
        }
        finally
        {
            await _docs.CloseAsync(save: false);
        }

        // act: импортировать обратно как деталь
        await _conv.ImportStepAsync(path, KompasDocumentType.Part);
        try
        {
            // assert: геометрия пришла — ненулевой объём (40·30·10 = 12000 мм³)
            var info = await _query.GetPartInfoAsync();
            Assert.InRange(info.Volume, 12000 * 0.95, 12000 * 1.05);
        }
        finally
        {
            await _docs.CloseAsync(save: false);
        }
    }

    [Fact]
    public async Task Lists_components_of_imported_assembly()
    {
        // Реальная сборка кейса (gitignored); если её нет локально — тест пропускается.
        var caseStep = Path.Combine(TestPaths.RepoRoot(),
            "usecases", "0002-voron-pug-strain-relief-2mm", "source", "G2E_PUG.step");
        if (!File.Exists(caseStep)) return; // gitignored кейс отсутствует локально — пропускаем

        await _conv.ImportStepAsync(caseStep, KompasDocumentType.Assembly);
        try
        {
            var comps = await _query.ListComponentsAsync();

            Assert.True(comps.Count >= 2, $"Ожидалось ≥2 компонента, получено {comps.Count}.");
            Assert.All(comps, c => Assert.False(string.IsNullOrWhiteSpace(c.Name)));
            Assert.Contains(comps, c => c.Name.Contains("spacer", StringComparison.OrdinalIgnoreCase));
        }
        finally
        {
            await _docs.CloseAsync(save: false);
        }
    }
}
