using System.Collections.Generic;
using System.Text.Json;
using LazyBear.MCP.Services.ToolRegistry;
using RestSharp;

namespace LazyBear.MCP.Services.GitLab;

/// <summary>
/// Базовый класс для всех инструментов GitLab
/// </summary>
public sealed class GitLabToolsBase
{
    protected readonly GitLabApiClient _client;
    protected readonly string _baseUrl;
    protected readonly int _perPageDefault;

    private readonly string _token;
    private readonly string _baseUrlConfig;
    private readonly ToolRegistryService _registry;

    /// <summary>
    /// Ошибка инициализации клиента (если возникла)
    /// </summary>
    protected string? ClientInitializationError { get; }

    /// <summary>
    /// Конструктор
    /// </summary>
    /// <param name="baseUrlConfig">Конфигурация URL</param>
    /// <param name="token">API токен</param>
    /// <param name="registry">Регистратор инструментов</param>
    public GitLabToolsBase(
        string baseUrlConfig,
        string token,
        ToolRegistryService registry)
    {
        _token = token;
        _baseUrlConfig = baseUrlConfig;
        _registry = registry;

        // Инициализация клиента
        _baseUrl = baseUrlConfig;
        _client = new GitLabApiClient(baseUrlConfig);
    }

    /// <summary>
    /// Проверка, активирован ли инструмент в TUI
    /// </summary>
    protected bool TryCheckEnabled(string toolName, out string error)
    {
        if (!_registry.IsToolEnabled("GitLab", toolName))
        {
            error = $"Инструмент '{toolName}' модуля GitLab отключён в TUI.";
            return false;
        }
        error = string.Empty;
        return true;
    }

    /// <summary>
    /// Получение клиента RestSharp
    /// </summary>
    protected bool TryGetClient(out GitLabApiClient client, out string error)
    {
        client = _client;
        error = ClientInitializationError is null
            ? string.Empty
            : $"GitLab клиент не инициализирован. Проверьте GitLab:Url. Детали: {ClientInitializationError}";
        return ClientInitializationError is null;
    }

    /// <summary>
    /// Создание запроса к GitLab API
    /// </summary>
    protected RestRequest CreateRequest(string resource, RestSharp.Method method = RestSharp.Method.Get)
    {
        var request = _client.GetRequest(resource);
        return request;
    }

    /// <summary>
    /// Форматирование ошибки ответа от GitLab API
    /// </summary>
    protected string FormatResponseError(string toolName, RestResponse response, string? resource = null)
    {
        var resourcePart = string.IsNullOrWhiteSpace(resource)
            ? string.Empty
            : $", resource='{resource}'";
        var body = string.IsNullOrWhiteSpace(response.Content)
            ? "-"
            : response.Content;
        return $"Ошибка GitLab в tool '{toolName}'{resourcePart}: status={(int)response.StatusCode}, details={body}";
    }

    /// <summary>
    /// Форматирование исключения
    /// </summary>
    protected string FormatException(string toolName, Exception exception, string? resource = null)
    {
        var resourcePart = string.IsNullOrWhiteSpace(resource)
            ? string.Empty
            : $", resource='{resource}'";
        return $"Ошибка GitLab в tool '{toolName}'{resourcePart}: {exception.GetType().Name}: {exception.Message}";
    }

    /// <summary>
    /// Получение вложенного строки из Json
    /// </summary>
    protected static string? GetNestedString(JsonElement element, params string[] path)
    {
        var current = element;

        foreach (var segment in path)
        {
            if (!current.TryGetProperty(segment, out current))
            {
                return null;
            }
        }

        return current.ValueKind == JsonValueKind.String
            ? current.GetString()
            : current.ToString();
    }

    /// <summary>
    /// Экстракция текста из комментариев GitLab
    /// </summary>
    protected static string ExtractCommentText(JsonElement body)
    {
        var chunks = new List<string>();
        CollectText(body, chunks);
        return chunks.Count == 0 ? "-" : string.Join(" ", chunks);
    }

    /// <summary>
    /// Рекурсивный сбор текста из JSON
    /// </summary>
    protected static void CollectText(JsonElement element, List<string> chunks)
    {
        if (element.ValueKind == JsonValueKind.Object)
        {
            // Ищем текстовый узел в структуре комментария GitLab
            if (element.TryGetProperty("body", out var bodyElement) &&
                bodyElement.TryGetProperty("text", out var textElement))
            {
                if (textElement.ValueKind == JsonValueKind.String)
                {
                    chunks.Add(textElement.GetString() ?? string.Empty);
                }
            }

            foreach (var property in element.EnumerateObject())
            {
                CollectText(property.Value, chunks);
            }

            return;
        }

        if (element.ValueKind == JsonValueKind.Array)
        {
            foreach (var item in element.EnumerateArray())
            {
                CollectText(item, chunks);
            }
        }
    }
}