using System.Runtime.Versioning;

namespace Kompas.Mcp.Core.Validation;

/// <summary>
/// Авто-валидация: дописывает к ответу мутирующей операции результат проверки построения.
/// Операция может «пройти» (<c>Create()/Update()==true</c>), оставив деталь в ошибке, поэтому
/// проверка идёт сразу после каждой операции — агенту не нужно звать validate_part отдельно.
/// Режим переключается на лету (<c>set_auto_validate</c>) или при старте
/// (<see cref="AutoValidationSettings.EnvironmentVariable"/>).
/// </summary>
[SupportedOSPlatform("windows")]
public sealed class AutoValidation
{
    private readonly ValidationService _validation;
    private volatile bool _enabled;

    public AutoValidation(ValidationService validation)
        : this(validation, AutoValidationSettings.ReadFromEnvironment())
    {
    }

    public AutoValidation(ValidationService validation, bool enabled)
    {
        _validation = validation ?? throw new ArgumentNullException(nameof(validation));
        _enabled = enabled;
    }

    /// <summary>Включена ли авто-валидация.</summary>
    public bool Enabled
    {
        get => _enabled;
        set => _enabled = value;
    }

    /// <summary>
    /// Дописать к сообщению об успехе результат проверки построения. При выключенном режиме и при
    /// сбое самой проверки сообщение возвращается как есть: авто-валидация никогда не превращает
    /// удачную операцию в ошибку.
    /// </summary>
    public async Task<string> AnnotateAsync(string message, CancellationToken ct = default)
    {
        if (!_enabled) return message;

        IReadOnlyList<OperationError> errors;
        try
        {
            errors = await _validation.ValidatePartAsync(ct).ConfigureAwait(false);
        }
        catch (Exception ex)
        {
            return $"{message} (проверка построения недоступна: {ex.Message})";
        }

        if (errors.Count == 0) return message + " Построение чистое.";

        var lines = errors.Select(e => $"\"{e.Name}\" (код {e.ErrorCode}: {e.Description})");
        return message + $" ⚠ Внимание: {errors.Count} операц. в ошибке: " + string.Join("; ", lines) +
               ". Результат может быть некорректным.";
    }
}
