using ClawdDotNet.Core.Audit;
using ClawdDotNet.Core.Config;
using ClawdDotNet.Core.Engine;
using ClawdDotNet.Core.Security;
using ClawdDotNet.Core.Staging;
using ClawdDotNet.Core.Tools;

namespace ClawdDotNet.Core.Tests.Infrastructure;

/// <summary>
/// Baut eine einsatzbereite AgentEngine mit Fake-Client, Fake-Tools und
/// In-Memory-State zusammen.
/// </summary>
internal sealed class EngineFixture
{
    public FakeChatClient Client { get; } = new();
    public ToolRegistry Registry { get; } = new();
    public InMemoryStateStore StateStore { get; } = new();
    public AgentEngine Engine { get; }

    private readonly List<AgentConfig> _agents = new();

    /// <summary>Die registrierten Agenten — für Tests, die einen Dispatcher selbst bauen.</summary>
    public IReadOnlyList<AgentConfig> Agents => _agents;

    public EngineFixture(IAuditRepository? audit = null, StagingGate? staging = null)
    {
        Engine = new AgentEngine(
            Client,
            Registry,
            new PermissionGate(),
            StateStore,
            TestLogging.Factory,
            auditRepository: audit,
            stagingGate: staging);

        // Kein Agent-Verzeichnis → keine Persistenz auf die Platte während der Tests.
        Engine.SetAgentConfigProvider(() => _agents, "test-instance", _ => null);
    }

    public EngineFixture WithTool(IAgentTool tool)
    {
        Registry.Register(tool);
        return this;
    }

    public AgentConfig AddAgent(string agentId, params string[] toolNames)
    {
        var config = new AgentConfig
        {
            AgentId = agentId,
            DisplayName = agentId,
            Model = "test/model",
            SystemPrompt = $"Du bist {agentId}.",
            LoopGuard = new LoopGuardConfig
            {
                MaxSteps = 50,
                MaxCumulativeTokens = 10_000_000,
                TimeoutSeconds = 60,
                MaxContextTokens = 10_000_000    // Compaction in Engine-Tests ausschalten
            }
        };

        foreach (var name in toolNames)
            config.Tools[name] = new Dictionary<string, object?>();

        _agents.Add(config);
        return config;
    }
}
