using ClaudeDo.Data;
using ClaudeDo.Worker.Hub;
using ClaudeDo.Worker.Planning;
using ClaudeDo.Worker.Queue;
using ClaudeDo.Worker.State;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging.Abstractions;

namespace ClaudeDo.Worker.Tests.Infrastructure;

/// Test-only helper that wires TaskStateService and PlanningChainCoordinator
/// against a shared DB factory, breaking the Func cycle between them.
public static class TaskStateServiceBuilder
{
    public sealed record Built(
        TaskStateService State,
        PlanningChainCoordinator Chain,
        CapturingHubContext Hub,
        Func<int> WakeCount,
        CountingQueueWaker Waker);

    public static Built Build(IDbContextFactory<ClaudeDoDbContext> dbFactory)
    {
        var hub = new CapturingHubContext();
        var broadcaster = new HubBroadcaster(hub);
        var waker = new CountingQueueWaker();

        TaskStateService? state = null;
        var chain = new PlanningChainCoordinator(dbFactory, () => state!);
        state = new TaskStateService(
            dbFactory,
            broadcaster,
            waker,
            chain,
            NullLogger<TaskStateService>.Instance);

        return new Built(state, chain, hub, () => waker.Count, waker);
    }
}

public sealed class CountingQueueWaker : IQueueWaker
{
    private int _count;
    public int Count => Volatile.Read(ref _count);
    public void Wake() => Interlocked.Increment(ref _count);
}
