using System.Runtime.Versioning;
using Kompas.Mcp.Core.Threading;
using Kompas6API5;

namespace Kompas.Mcp.Core.Vision;

/// <summary>Результат снимка модели.</summary>
public sealed record SnapshotResult
{
    public required byte[] Bytes { get; init; }
    public required RasterImageFormat Format { get; init; }
    public string MimeType => Format.MimeType();
}

/// <summary>
/// «Зрение агента»: рендер активного 3D-документа в растр (PNG и пр.) прямо в память
/// через API5 <c>ksDocument3D.SaveAsToRasterFormat</c> + <c>resultArrayBytes</c>.
/// </summary>
[SupportedOSPlatform("windows")]
public sealed class SnapshotService
{
    private readonly KompasSession _session;
    private readonly KompasDispatcher _dispatcher;

    public SnapshotService(KompasSession session, KompasDispatcher dispatcher)
    {
        _session = session ?? throw new ArgumentNullException(nameof(session));
        _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
    }

    /// <summary>
    /// Снять текущий вид активного 3D-документа в растр.
    /// </summary>
    /// <param name="format">Формат изображения (по умолчанию PNG).</param>
    /// <param name="resolution">Разрешение, DPI; 0 — текущее экранное.</param>
    /// <param name="greyScale">Сохранять в оттенках серого.</param>
    /// <param name="saveToFile">Если задан — дополнительно записать файл по пути.</param>
    public Task<SnapshotResult> CaptureActiveModelAsync(
        RasterImageFormat format = RasterImageFormat.Png,
        int resolution = 0,
        bool greyScale = false,
        string? saveToFile = null,
        CancellationToken ct = default)
        => _dispatcher.InvokeAsync(() => CaptureCore(format, resolution, greyScale, saveToFile), ct);

    private SnapshotResult CaptureCore(RasterImageFormat format, int resolution, bool greyScale, string? saveToFile)
    {
        var doc3d = _session.Kompas.ActiveDocument3D() as ksDocument3D
            ?? throw new InvalidOperationException("Нет активного 3D-документа для снимка.");

        var param = doc3d.RasterFormatParam() as ksRasterFormatParam
            ?? throw new InvalidOperationException("Не удалось получить ksRasterFormatParam.");

        param.Init();
        param.format = (short)format;
        param.colorBPP = 24;
        param.extResolution = resolution;
        param.greyScale = greyScale;
        param.onlyThinLine = false;

        // Рендерим в файл и читаем байты обратно: для 3D-документа resultArrayBytes
        // при заданном имени файла не заполняется (см. docs/OPEN_QUESTIONS.md), а файловый
        // вывод работает надёжно.
        param.returnResultAsArrayBytes = false;

        var outFile = saveToFile is null
            ? Path.Combine(Path.GetTempPath(), $"kompas-snap-{Guid.NewGuid():N}.{format.FileExtension()}")
            : Documents.OutputPath.Prepare(saveToFile, nameof(saveToFile));
        var deleteAfter = saveToFile is null;

        try
        {
            if (!doc3d.SaveAsToRasterFormat(outFile, param))
                throw new InvalidOperationException("SaveAsToRasterFormat вернул FALSE (рендер не удался).");
            if (!File.Exists(outFile))
                throw new InvalidOperationException("Файл снимка не создан.");

            var bytes = File.ReadAllBytes(outFile);
            if (bytes.Length == 0)
                throw new InvalidOperationException("Снимок пуст.");

            return new SnapshotResult { Bytes = bytes, Format = format };
        }
        finally
        {
            if (deleteAfter && File.Exists(outFile))
            {
                try { File.Delete(outFile); } catch { /* временный файл — не критично */ }
            }
        }
    }
}
