using System.ComponentModel;
using ClaudeDo.Worker.Findings;
using ClaudeDo.Worker.Git;
using ModelContextProtocol.Server;

namespace ClaudeDo.Worker.Runner;

public sealed record SaveTaskFindingResult(
    bool Saved, string Slug, string Path, int TotalFindings, bool NearCapacity);

[McpServerToolType]
public sealed class TaskRunFindingsMcpTools
{
    private readonly FindingsStore _store;
    private readonly FindingsStoreLocator _locator;
    private readonly TaskRunMcpContextAccessor _ctx;

    public TaskRunFindingsMcpTools(
        FindingsStore store, FindingsStoreLocator locator, TaskRunMcpContextAccessor ctx)
    {
        _store = store;
        _locator = locator;
        _ctx = ctx;
    }

    [McpServerTool, Description(
        "Record a durable trap you just hit, so future runs read it instead of losing the same " +
        "turns. Only for findings that are lasting, non-obvious and behaviour-changing (\"X looks " +
        "like Y but is Z — do W instead\"); a bug you fixed is git history, not a finding. When " +
        "unsure, don't. Re-using a slug overwrites it. Writes to this task's own project; " +
        "nearCapacity=true means prune before adding more.")]
    public async Task<SaveTaskFindingResult> SaveFinding(
        [Description("Stable lowercase kebab-case id, max 60 chars, e.g. 'conpty-arg-quoting'. Same slug overwrites.")] string slug,
        [Description("One full sentence stating the trap itself — this is the index line other agents scan.")] string title,
        [Description("2-6 sentences: what happens, why it does not look like that, what to do instead.")] string body,
        [Description("Repo-relative path or subsystem the finding applies to, e.g. 'src/ClaudeDo.Worker/Planning'.")] string scope = "",
        CancellationToken cancellationToken = default)
    {
        var taskId = _ctx.Current.CallerTaskId;
        var target = await _locator.ResolveForTaskAsync(taskId, cancellationToken);
        var head = await GitHead.ShortAsync(target.WorkingDir, cancellationToken);

        var outcome = await _store.SaveAsync(
            target.WorkingDir,
            new FindingInput(slug, title, body, scope, SourceTaskId: taskId, VerifiedAgainst: head),
            cancellationToken,
            target.Tracked);

        return new SaveTaskFindingResult(
            true, outcome.Slug, outcome.Path, outcome.TotalFindings, outcome.NearCapacity);
    }
}
