using System.Text.Json;
using ClawdDotNet.Core.Tools;
using Microsoft.Extensions.Logging;

namespace ClawdDotNet.Tools.AgentComm;

public sealed class AgentCommTool : IAgentTool
{
    public string Name => "AgentComm";

    public string Description =>
        "Ermöglicht die Kommunikation mit anderen Agenten in der gleichen Instanz. " +
        "Du kannst Agenten auflisten und ihnen Nachrichten senden.";

    public JsonElement InputSchema { get; } = JsonDocument.Parse("""
        {
            "type": "object",
            "properties": {
                "action": {
                    "type": "string",
                    "enum": ["list_agents", "send_message"],
                    "description": "Die auszuführende Aktion: 'list_agents' listet alle verfügbaren Agenten auf, 'send_message' sendet eine Nachricht an einen anderen Agenten und wartet auf dessen Antwort."
                },
                "targetAgentId": {
                    "type": "string",
                    "description": "Die ID des Ziel-Agenten (nur für send_message erforderlich)"
                },
                "message": {
                    "type": "string",
                    "description": "Die Nachricht an den Ziel-Agenten (nur für send_message erforderlich)"
                }
            },
            "required": ["action"]
        }
        """).RootElement.Clone();

    public async Task<ToolResult> ExecuteAsync(
        JsonElement input, AgentToolContext context, CancellationToken ct)
    {
        var action = input.TryGetProperty("action", out var actionEl)
            ? actionEl.GetString() : null;

        if (context.MessageRouter is null)
            return ToolResult.Fail("AgentComm ist nicht verfügbar: Kein MessageRouter konfiguriert.");

        switch (action)
        {
            case "list_agents":
                return ListAgents(context);

            case "send_message":
                return await SendMessage(input, context, ct);

            default:
                return ToolResult.Fail($"Unbekannte Aktion: '{action}'. Verwende 'list_agents' oder 'send_message'.");
        }
    }

    private static ToolResult ListAgents(AgentToolContext context)
    {
        var agents = context.MessageRouter!.ListAgents(context.AgentId);

        if (agents.Count == 0)
            return ToolResult.Ok(JsonSerializer.Serialize(new
            {
                info = "Keine anderen Agenten in dieser Instanz gefunden.",
                agents = Array.Empty<object>()
            }));

        var result = agents.Select(a => new
        {
            agentId = a.AgentId,
            displayName = a.DisplayName,
            role = a.Role,
            model = a.Model,
            status = a.IsRunning ? "running" : "idle"
        });

        return ToolResult.Ok(JsonSerializer.Serialize(new { agents = result }));
    }

    private static async Task<ToolResult> SendMessage(
        JsonElement input, AgentToolContext context, CancellationToken ct)
    {
        var targetId = input.TryGetProperty("targetAgentId", out var tid) ? tid.GetString() : null;
        var message = input.TryGetProperty("message", out var msg) ? msg.GetString() : null;

        if (string.IsNullOrWhiteSpace(targetId))
            return ToolResult.Fail("'targetAgentId' ist erforderlich für send_message.");

        if (string.IsNullOrWhiteSpace(message))
            return ToolResult.Fail("'message' ist erforderlich für send_message.");

        if (targetId == context.AgentId)
            return ToolResult.Fail("Du kannst dir nicht selbst eine Nachricht senden.");

        context.Logger.LogInformation(
            "Agent {From} sendet Nachricht an {To}: {Msg}",
            context.AgentId, targetId, message.Length > 100 ? message[..100] + "..." : message);

        var result = await context.MessageRouter!.SendMessageAsync(
            context.AgentId, targetId, message, ct);

        if (result.Delivered)
        {
            return ToolResult.Ok(JsonSerializer.Serialize(new
            {
                delivered = true,
                targetAgentId = targetId,
                response = result.Response
            }));
        }

        return ToolResult.Fail($"Nachricht konnte nicht zugestellt werden: {result.Error}");
    }
}
