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

namespace ClawdDotNet.Tools.AgentSpawn;

public sealed class AgentSpawnTool : IAgentTool
{
    public string Name => "AgentSpawn";

    public string Description =>
        "Ermöglicht es, andere Agenten zu starten und ihnen eine Aufgabe zuzuweisen. " +
        "Der Zielagent wird als eigenständiger Run gestartet und führt die Aufgabe unabhängig aus. " +
        "Verwende dies, um Aufgaben an spezialisierte Agenten zu delegieren.";

    public JsonElement InputSchema { get; } = JsonDocument.Parse("""
        {
            "type": "object",
            "properties": {
                "action": {
                    "type": "string",
                    "enum": ["list_agents", "spawn_agent"],
                    "description": "Die auszuführende Aktion: 'list_agents' listet alle verfügbaren Agenten auf, 'spawn_agent' startet einen Agenten mit einer Aufgabe."
                },
                "targetAgentId": {
                    "type": "string",
                    "description": "Die ID des Ziel-Agenten (nur für spawn_agent erforderlich)"
                },
                "taskMessage": {
                    "type": "string",
                    "description": "Die Aufgabe/Anweisung für den Ziel-Agenten (nur für spawn_agent 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("AgentSpawn ist nicht verfügbar: Kein MessageRouter konfiguriert.");

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

            case "spawn_agent":
                return await SpawnAgent(input, context, ct);

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

    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> SpawnAgent(
        JsonElement input, AgentToolContext context, CancellationToken ct)
    {
        var targetId = input.TryGetProperty("targetAgentId", out var tid) ? tid.GetString() : null;
        var taskMessage = input.TryGetProperty("taskMessage", out var msg) ? msg.GetString() : null;

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

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

        if (targetId == context.AgentId)
            return ToolResult.Fail("Du kannst dich nicht selbst spawnen.");

        context.Logger.LogInformation(
            "Agent {From} spawnt Agent {To} mit Aufgabe: {Task}",
            context.AgentId, targetId,
            taskMessage.Length > 100 ? taskMessage[..100] + "..." : taskMessage);

        var result = await context.MessageRouter!.SpawnAgentAsync(
            context.AgentId, targetId, taskMessage, ct);

        if (result.Started)
        {
            return ToolResult.Ok(JsonSerializer.Serialize(new
            {
                spawned = true,
                targetAgentId = result.AgentId,
                result = result.FinalMessage
            }));
        }

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