using System.ComponentModel;
using ClaudeDo.Data.Repositories;
using ClaudeDo.Worker.Hub;
using ModelContextProtocol.Server;

namespace ClaudeDo.Worker.Runner;

public sealed record SuggestedImprovementDto(string ChildTaskId);

[McpServerToolType]
public sealed class TaskRunMcpService
{
    private readonly TaskRepository _tasks;
    private readonly TaskRunMcpContextAccessor _ctx;
    private readonly HubBroadcaster _broadcaster;

    public TaskRunMcpService(TaskRepository tasks, TaskRunMcpContextAccessor ctx, HubBroadcaster broadcaster)
    {
        _tasks = tasks;
        _ctx = ctx;
        _broadcaster = broadcaster;
    }

    [McpServerTool, Description(
        "File an out-of-scope improvement as a child task of the current task. The child runs " +
        "automatically after this task finishes and is surfaced for review alongside it. Use ONLY " +
        "for work that is genuinely outside this task's scope (a refactor, follow-up, or tech debt) " +
        "— never for work that belongs to the current task. Set model to the cheapest model that can " +
        "do the follow-up well — 'haiku' for trivial/mechanical work, 'sonnet' for normal coding, " +
        "'opus' only for complex work. Leave model null to inherit the list/global default.")]
    public async Task<SuggestedImprovementDto> SuggestImprovement(
        string title,
        string description,
        string? model,
        CancellationToken cancellationToken)
    {
        var callerId = _ctx.Current.CallerTaskId;
        var caller = await _tasks.GetByIdAsync(callerId, cancellationToken)
            ?? throw new InvalidOperationException("Calling task not found.");
        if (caller.ParentTaskId is not null)
            throw new InvalidOperationException(
                "A child task cannot suggest further improvements (improvements are one layer deep).");

        var child = await _tasks.CreateChildAsync(
            callerId, title, description, commitType: null, createdBy: callerId, model: model, ct: cancellationToken);
        await _broadcaster.TaskUpdated(child.Id);
        await _broadcaster.TaskUpdated(callerId);
        return new SuggestedImprovementDto(child.Id);
    }
}
