using System.ComponentModel;
using Kompas.Mcp.Core;
using Kompas.Mcp.Core.Assemblies;
using Kompas.Mcp.Core.Validation;
using ModelContextProtocol.Server;

namespace Kompas.Mcp.Host.Tools;

/// <summary>Инструменты работы со сборками (вставка/сопряжение компонентов).</summary>
[McpServerToolType]
public sealed class AssemblyTools(KompasSession session, AssemblyService assembly, AutoValidation autoValidation)
{
    [McpServerTool(Name = "assembly_add_component")]
    [Description("Вставить компонент (деталь .m3d или подсборку .a3d) из файла в активную сборку. " +
        "Активный документ должен быть сборкой (document_create assembly). origin компонента — точка (x,y,z) в мм " +
        "мировой СК сборки (по умолчанию начало координат). Деталь-источник должна быть сохранена в файл " +
        "(document_save_as). Возвращает индекс и имя вставленного компонента.")]
    public async Task<string> AddComponent(
        [Description("Путь к файлу-источнику компонента (.m3d/.a3d)")] string filePath,
        [Description("X положения origin компонента, мм")] double x = 0,
        [Description("Y положения origin компонента, мм")] double y = 0,
        [Description("Z положения origin компонента, мм")] double z = 0)
    {
        await session.ConnectAsync();
        var c = await assembly.AddComponentAsync(filePath, x, y, z);
        return await autoValidation.AnnotateAsync(
            $"Компонент '{c.Name}' вставлен в сборку, индекс {c.Index}, позиция ({x}, {y}, {z}).");
    }

    [McpServerTool(Name = "assembly_add_mate")]
    [Description("Наложить сопряжение между гранями ДВУХ компонентов активной сборки, выбранными по " +
        "мировым точкам (x1,y1,z1) и (x2,y2,z2) — точки в СЕРЕДИНЕ граней (мм). mateType: " +
        "'coincidence' (совпадение, грани заподлицо) или 'distance' (на расстоянии value мм между гранями). " +
        "Решатель спозиционирует компоненты. Сделайте model_snapshot/describe_face, прикиньте точки на гранях.")]
    public async Task<string> AddMate(
        [Description("Тип сопряжения: coincidence | distance")] string mateType,
        [Description("X точки на грани компонента 1, мм")] double x1,
        [Description("Y точки на грани компонента 1, мм")] double y1,
        [Description("Z точки на грани компонента 1, мм")] double z1,
        [Description("X точки на грани компонента 2, мм")] double x2,
        [Description("Y точки на грани компонента 2, мм")] double y2,
        [Description("Z точки на грани компонента 2, мм")] double z2,
        [Description("Зазор для distance, мм (для coincidence не нужен)")] double value = 0)
    {
        await session.ConnectAsync();
        var type = Mates.Parse(mateType);
        var m = await assembly.AddMateAsync(type, x1, y1, z1, x2, y2, z2, value);
        var valueText = Mates.RequiresValue(type) ? $", значение {value} мм" : "";
        return await autoValidation.AnnotateAsync($"Сопряжение '{type}'{valueText} наложено (valid={m.Valid}).");
    }
}
