using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Nodes;
using Nexus.Api.Models;

namespace Nexus.Api.Services;

/// <summary>
/// Temporary, bounded HTTP compatibility adapter for session history.
/// All OpenClaw inventory and management operations use the Protocol-v4
/// connector and <see cref="IOpenClawControlService"/>.
/// </summary>
public sealed class OpenClawGatewayClient(
    HttpClient httpClient,
    IConfiguration configuration) : IOpenClawGatewayClient
{
    private static readonly string[] SensitiveMarkers =
    [
        "api_key", "apikey", "api-key", "authorization", "bearer ", "password",
        "token", "secret", "x-nexus-api-key", "jwt", "private_key"
    ];

    public async Task<List<MessageEntry>> GetSessionHistoryAsync(
        string sessionKey,
        int limit = 50,
        int offset = 0)
    {
        var result = new List<MessageEntry>();
        try
        {
            var toolResult = await InvokeToolAsync("sessions_history", new
            {
                sessionKey,
                limit,
                offset,
                includeTools = false
            });
            if (toolResult is null)
                return result;

            using var document = JsonDocument.Parse(toolResult.ToJsonString());
            var root = document.RootElement;
            if (!TryGetMessages(root, out var messages))
                return result;

            foreach (var message in messages.EnumerateArray())
            {
                if (!message.TryGetProperty("role", out var roleElement))
                    continue;

                var role = roleElement.GetString();
                if (role is not ("user" or "assistant"))
                    continue;
                if (!message.TryGetProperty("content", out var contentElement) ||
                    contentElement.ValueKind != JsonValueKind.Array)
                {
                    continue;
                }

                var text = contentElement
                    .EnumerateArray()
                    .Where(block =>
                        block.TryGetProperty("type", out var type) &&
                        type.GetString() == "text" &&
                        block.TryGetProperty("text", out _))
                    .Select(block => block.GetProperty("text").GetString())
                    .Where(value => !string.IsNullOrWhiteSpace(value));
                var content = string.Join(" ", text).Trim();
                if (string.IsNullOrWhiteSpace(content) ||
                    content is "REPLY_SKIP" or "ANNOUNCE_SKIP")
                {
                    continue;
                }

                var timestamp = message.TryGetProperty("timestamp", out var timestampElement)
                    ? timestampElement.GetString()
                    : null;
                result.Add(new MessageEntry(
                    role,
                    content,
                    timestamp ?? DateTimeOffset.UtcNow.ToString("O")));
            }
        }
        catch
        {
            // Session history is an optional dashboard projection. The caller
            // handles an empty result without inventing messages.
        }

        return result;
    }

    public static string RedactSensitiveText(string content)
    {
        if (string.IsNullOrWhiteSpace(content))
            return content;

        var lines = content.Split('\n');
        for (var index = 0; index < lines.Length; index++)
        {
            var lower = lines[index].ToLowerInvariant();
            if (SensitiveMarkers.Any(marker =>
                    lower.Contains(marker, StringComparison.OrdinalIgnoreCase)))
            {
                lines[index] = "[redacted sensitive line]";
            }
        }

        return string.Join('\n', lines);
    }

    private async Task<JsonNode?> InvokeToolAsync(string tool, object args)
    {
        using var request = new HttpRequestMessage(HttpMethod.Post, "/tools/invoke");
        var credential = configuration["Integrations:OpenClaw:Password"];
        if (string.IsNullOrWhiteSpace(credential))
            credential = configuration["Integrations:OpenClaw:Token"];
        if (!string.IsNullOrWhiteSpace(credential))
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", credential);

        request.Content = JsonContent.Create(new Dictionary<string, object?>
        {
            ["tool"] = tool,
            ["args"] = args
        });

        using var response = await httpClient.SendAsync(request);
        if (!response.IsSuccessStatusCode)
            return null;

        var json = await response.Content.ReadAsStringAsync();
        if (string.IsNullOrWhiteSpace(json))
            return null;

        var node = JsonNode.Parse(json);
        return node?["ok"]?.GetValue<bool>() == true && node["result"] is not null
            ? node["result"]
            : node;
    }

    private static bool TryGetMessages(
        JsonElement root,
        out JsonElement messages)
    {
        if (root.TryGetProperty("details", out var details) &&
            details.TryGetProperty("messages", out messages) &&
            messages.ValueKind == JsonValueKind.Array)
        {
            return true;
        }

        if (root.TryGetProperty("messages", out messages) &&
            messages.ValueKind == JsonValueKind.Array)
        {
            return true;
        }

        messages = default;
        return false;
    }
}
