using System.ComponentModel;
using Kompas.Mcp.Core;
using Kompas.Mcp.Core.Documents;
using Kompas.Mcp.Core.Modeling;
using ModelContextProtocol.Server;

namespace Kompas.Mcp.Host.Tools;

/// <summary>Инструменты управления документами.</summary>
[McpServerToolType]
public sealed class DocumentTools(KompasSession session, DocumentService docs, PartModeler modeler)
{
    [McpServerTool(Name = "document_create")]
    [Description("Создать новый документ и сделать его активным. type: part | assembly | drawing | fragment | specification | text.")]
    public async Task<string> Create([Description("Тип документа")] string type)
    {
        await session.ConnectAsync();
        var info = await docs.CreateAsync(DocumentTypes.Parse(type));
        await modeler.ResetAsync(); // прежние id эскизов/операций недействительны
        return $"Создан документ типа {info.Type}.";
    }

    [McpServerTool(Name = "document_open")]
    [Description("Открыть документ КОМПАС с диска по полному пути.")]
    public async Task<string> Open(
        [Description("Полный путь к файлу")] string path,
        [Description("Открыть только для чтения")] bool readOnly = false)
    {
        await session.ConnectAsync();
        var info = await docs.OpenAsync(path, readOnly);
        await modeler.ResetAsync();
        return $"Открыт документ: {info.Name} ({info.Type}).";
    }

    [McpServerTool(Name = "document_save")]
    [Description("Сохранить активный документ. Для нового (ещё не сохранённого) документа передайте path — " +
                 "полный путь с расширением: .m3d (деталь), .a3d (сборка), .cdw (чертёж), .frw (фрагмент). " +
                 "Без path документ сохраняется туда, откуда открыт (только для уже сохранённого ранее). " +
                 "path также используют, чтобы сохранить копию под новым именем.")]
    public async Task<string> Save(
        [Description("Полный путь файла с расширением; пусто — сохранить на прежнее место")] string? path = null)
    {
        await session.ConnectAsync();
        if (string.IsNullOrWhiteSpace(path))
        {
            await docs.SaveAsync();
            return "Документ сохранён.";
        }

        var saved = await docs.SaveAsAsync(path);
        return $"Сохранено: {saved}";
    }

    [McpServerTool(Name = "document_close")]
    [Description("Закрыть активный документ. save — сохранять ли изменения при закрытии. " +
                 "all=true закрывает ВСЕ открытые документы БЕЗ сохранения — этим освобождают имя файла, " +
                 "занятое другим открытым документом (иначе КОМПАС молча не перезапишет его).")]
    public async Task<string> Close(
        [Description("Сохранять изменения")] bool save = false,
        [Description("Закрыть все открытые документы без сохранения")] bool all = false)
    {
        await session.ConnectAsync();
        if (all)
        {
            var closed = await docs.CloseAllAsync();
            await modeler.ResetAsync();
            return $"Закрыто документов: {closed} (без сохранения).";
        }

        var ok = await docs.CloseAsync(save);
        await modeler.ResetAsync();
        return ok ? "Документ закрыт." : "Не удалось закрыть документ.";
    }

    [McpServerTool(Name = "set_part_info")]
    [Description("Задать наименование и/или обозначение детали (сборки) активного 3D-документа. " +
                 "Наименование заменяет безликую «Деталь» в дереве построения и подставляется в штамп " +
                 "чертежа и в спецификацию, поэтому давайте его КАЖДОЙ детали, а не только перед выдачей. " +
                 "Не переданный параметр остаётся без изменений. Возвращает значения после записи.")]
    public async Task<string> SetPartInfo(
        [Description("Наименование детали, например «Значок декоративный»")] string? name = null,
        [Description("Обозначение по ЕСКД, например «ОМЕ.741124.001»")] string? marking = null)
    {
        await session.ConnectAsync();
        if (name is null && marking is null)
            throw new ArgumentException("Передайте name и/или marking — иначе менять нечего.");

        var identity = await docs.SetPartIdentityAsync(name, marking);
        var markingPart = identity.Marking.Length == 0 ? "" : $", обозначение «{identity.Marking}»";
        return $"Деталь: наименование «{identity.Name}»{markingPart}.";
    }

    [McpServerTool(Name = "document_active")]
    [Description("Сведения об активном документе.")]
    public async Task<string> Active()
    {
        await session.ConnectAsync();
        var i = await docs.GetActiveAsync();
        if (i is null) return "Нет активного документа.";
        var where = string.IsNullOrEmpty(i.PathName) ? "не сохранён" : i.PathName;
        return $"{i.Type}: {i.Name} ({where}).";
    }
}
