using Kompas.Mcp.Core.Documents;

namespace Kompas.Mcp.Tests.Integration;

/// <summary>Интеграция: жизненный цикл документов.</summary>
[Trait("Category", "Integration")]
[Collection(KompasCollection.Name)]
public sealed class DocumentTests : IntegrationTestBase
{
    private readonly DocumentService _docs;

    public DocumentTests(KompasFixture fx) : base(fx)
        => _docs = new DocumentService(fx.Session, fx.Dispatcher);

    [Fact]
    public async Task Create_part_saveas_close_roundtrip()
    {
        var created = await _docs.CreateAsync(KompasDocumentType.Part);
        Assert.Equal(KompasDocumentType.Part, created.Type);

        var path = TestPaths.NewFile(".m3d");
        await _docs.SaveAsAsync(path);

        var active = await _docs.GetActiveAsync();
        Assert.NotNull(active);
        Assert.Equal(path, active!.PathName, ignoreCase: true);

        var closed = await _docs.CloseAsync(save: false);
        Assert.True(closed);
        Assert.True(File.Exists(path));
    }

    [Fact]
    public async Task SaveAs_over_a_name_held_by_another_open_document_fails_loudly()
    {
        // КОМПАС не перезаписывает файл, открытый другим документом, и НИЧЕГО об этом не сообщает:
        // SaveAs возвращает void. Без проверки по факту агент получает ложное «Сохранено».
        var path = TestPaths.NewFile(".m3d");
        await _docs.CreateAsync(KompasDocumentType.Part);
        await _docs.SaveAsAsync(path);   // первый документ занял имя и остался открытым

        await _docs.CreateAsync(KompasDocumentType.Part);
        try
        {
            var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => _docs.SaveAsAsync(path));
            Assert.Contains(path, ex.Message, StringComparison.OrdinalIgnoreCase);
        }
        finally
        {
            await _docs.CloseAsync(save: false);
            await _docs.CloseAsync(save: false);
        }
    }

    [Fact]
    public async Task SaveAs_creates_the_missing_directory()
    {
        // КОМПАС каталогов не создаёт: SaveAs в несуществующую папку молча ничего не пишет,
        // а прежняя диагностика винила «занятое имя файла» — агент чинил не ту причину.
        var path = Path.Combine(Path.GetDirectoryName(TestPaths.NewFile(".m3d"))!,
            "подпапка кейса", "деталь.m3d");
        Assert.False(Directory.Exists(Path.GetDirectoryName(path)));

        await _docs.CreateAsync(KompasDocumentType.Part);
        try
        {
            var saved = await _docs.SaveAsAsync(path);

            Assert.Equal(path, saved, ignoreCase: true);
            Assert.True(File.Exists(path), "файл не появился на диске");
        }
        finally
        {
            await _docs.CloseAsync(save: false);
            try { Directory.Delete(Path.GetDirectoryName(path)!, recursive: true); } catch (IOException) { }
        }
    }

    [Fact]
    public async Task Part_name_and_marking_survive_the_write()
    {
        await _docs.CreateAsync(KompasDocumentType.Part);
        try
        {
            var written = await _docs.SetPartIdentityAsync("Значок декоративный", "ОМЕ.741124.001");
            Assert.Equal("Значок декоративный", written.Name);
            Assert.Equal("ОМЕ.741124.001", written.Marking);

            // Незаданный параметр не затирает уже записанное.
            var partial = await _docs.SetPartIdentityAsync(name: null, marking: "ОМЕ.741124.002");
            Assert.Equal("Значок декоративный", partial.Name);
            Assert.Equal("ОМЕ.741124.002", partial.Marking);
        }
        finally { await _docs.CloseAsync(save: false); }
    }

    [Fact]
    public async Task Create_fragment_reports_type()
    {
        await _docs.CreateAsync(KompasDocumentType.Fragment);
        var active = await _docs.GetActiveAsync();
        Assert.NotNull(active);
        Assert.Equal(KompasDocumentType.Fragment, active!.Type);
        await _docs.CloseAsync(save: false);
    }
}
