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

namespace ClaudeDo.Worker.External;

public sealed record AddNoteResult(bool Saved, string Id, int AgentNotesToday, int RemainingToday);

[McpServerToolType]
public sealed class NotesMcpTools
{
    /// <summary>Agent-written notes allowed per day. The user's own notes are never counted or
    /// capped — this only stops an agent from burying the day in its own bullets.</summary>
    public const int DailyAgentCap = 10;

    /// <summary>A note is a line, not a report. Longer output belongs in a task or a finding.</summary>
    public const int MaxLength = 500;

    private readonly DailyNoteRepository _notes;
    private readonly HubBroadcaster _broadcaster;

    public NotesMcpTools(DailyNoteRepository notes, HubBroadcaster broadcaster)
    {
        _notes = notes;
        _broadcaster = broadcaster;
    }

    [McpServerTool, Description(
        "Add one short line to the user's notes for today — the day log they read in ClaudeDo, " +
        "not a log for you. Write only what the user would want to reread later and would " +
        "otherwise lose: a decision they made, something you found that changes their plans, " +
        "something they asked you to remember for the day. Task status, your progress and " +
        "anything already visible in the task list are noise here. When unsure, don't. " +
        "Capped at 10 agent notes per day; you cannot edit or delete notes, so a bad one stays " +
        "until the user removes it.")]
    public async Task<AddNoteResult> AddNote(
        [Description("The note itself: one plain sentence, no markdown, no prefix, max 500 characters.")] string text,
        CancellationToken cancellationToken = default)
    {
        var trimmed = (text ?? "").Trim();
        if (trimmed.Length == 0)
            throw new InvalidOperationException("text is required.");
        if (trimmed.Length > MaxLength)
            throw new InvalidOperationException(
                $"Note is {trimmed.Length} characters, the limit is {MaxLength}. Shorten it to one line.");

        var today = DateOnly.FromDateTime(DateTime.Today);
        var used = await _notes.CountAgentNotesAsync(today, cancellationToken);
        if (used >= DailyAgentCap)
            throw new InvalidOperationException(
                $"Daily cap reached: {DailyAgentCap} agent notes already written today. " +
                "Nothing was saved — tell the user instead of retrying.");

        var note = await _notes.AddAsync(today, trimmed, fromAgent: true, cancellationToken);
        await _broadcaster.NotesUpdated();
        return new AddNoteResult(true, note.Id, used + 1, DailyAgentCap - used - 1);
    }
}
