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

namespace ClaudeDo.Worker.External;

public sealed record ListSummaryDto(string Id, string Name, string? WorkingDir, string DefaultCommitType);

[McpServerToolType]
public sealed class ListMcpTools
{
    private readonly ListRepository _lists;
    private readonly HubBroadcaster _broadcaster;

    public ListMcpTools(ListRepository lists, HubBroadcaster broadcaster)
    {
        _lists = lists;
        _broadcaster = broadcaster;
    }

    [McpServerTool, Description("Create a new task list. workingDir sets the git repo tasks run against; commitType defaults to 'chore'.")]
    public async Task<ListSummaryDto> CreateList(
        string name, string? workingDir, string? commitType, CancellationToken cancellationToken)
    {
        if (string.IsNullOrWhiteSpace(name))
            throw new InvalidOperationException("name is required.");

        var entity = new ListEntity
        {
            Id = Guid.NewGuid().ToString(),
            Name = name,
            WorkingDir = workingDir.NullIfBlank(),
            DefaultCommitType = commitType.NullIfBlank() ?? CommitTypeRegistry.DefaultType,
            CreatedAt = DateTime.UtcNow,
        };
        await _lists.AddAsync(entity, cancellationToken);
        await _broadcaster.ListUpdated(entity.Id);
        return ToDto(entity);
    }

    [McpServerTool, Description("Rename a list and/or change its working dir and default commit type. Pass null to leave a field unchanged.")]
    public async Task<ListSummaryDto> UpdateList(
        string listId, string? name, string? workingDir, string? commitType, CancellationToken cancellationToken)
    {
        var entity = await _lists.GetByIdAsync(listId, cancellationToken)
            ?? throw new InvalidOperationException($"List {listId} not found.");

        if (name is not null && string.IsNullOrWhiteSpace(name))
            throw new InvalidOperationException("name cannot be blank.");
        if (name is not null) entity.Name = name;
        if (workingDir is not null)
            entity.WorkingDir = workingDir.NullIfBlank();
        if (commitType is not null)
            entity.DefaultCommitType = commitType.NullIfBlank() ?? CommitTypeRegistry.DefaultType;

        await _lists.UpdateAsync(entity, cancellationToken);
        await _broadcaster.ListUpdated(listId);
        return ToDto(entity);
    }

    [McpServerTool, Description("Delete a list and its tasks. Irreversible.")]
    public async Task DeleteList(string listId, CancellationToken cancellationToken)
    {
        _ = await _lists.GetByIdAsync(listId, cancellationToken)
            ?? throw new InvalidOperationException($"List {listId} not found.");
        await _lists.DeleteAsync(listId, cancellationToken);
        await _broadcaster.ListUpdated(listId);
    }

    private static ListSummaryDto ToDto(ListEntity l) =>
        new(l.Id, l.Name, l.WorkingDir, l.DefaultCommitType);
}
