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 TaskConfigDto(string? Model, string? SystemPrompt, string? AgentPath, int? MaxTurns);

[McpServerToolType]
public sealed class ConfigMcpTools
{
    private readonly ListRepository _lists;
    private readonly TaskRepository _tasks;
    private readonly HubBroadcaster _broadcaster;

    public ConfigMcpTools(ListRepository lists, TaskRepository tasks, HubBroadcaster broadcaster)
    {
        _lists = lists;
        _tasks = tasks;
        _broadcaster = broadcaster;
    }

    [McpServerTool, Description("Get a list's default config (model, system prompt, agent path). Returns null if no config is set.")]
    public async Task<TaskConfigDto?> GetListConfig(string listId, CancellationToken cancellationToken)
    {
        var cfg = await _lists.GetConfigAsync(listId, cancellationToken);
        return cfg is null ? null : new TaskConfigDto(cfg.Model, cfg.SystemPrompt, cfg.AgentPath, cfg.MaxTurns);
    }

    [McpServerTool, Description("Set a list's default model/system prompt/agent path/max turns. Passing all four as null clears the list config.")]
    public async Task SetListConfig(
        string listId, string? model, string? systemPrompt, string? agentPath, int? maxTurns, CancellationToken cancellationToken)
    {
        _ = await _lists.GetByIdAsync(listId, cancellationToken)
            ?? throw new InvalidOperationException($"List {listId} not found.");

        var m = model.NullIfBlank();
        var sp = systemPrompt.NullIfBlank();
        var ap = agentPath.NullIfBlank();

        if (m is null && sp is null && ap is null && maxTurns is null)
            await _lists.DeleteConfigAsync(listId, cancellationToken);
        else
            await _lists.SetConfigAsync(new ListConfigEntity
            {
                ListId = listId, Model = m, SystemPrompt = sp, AgentPath = ap, MaxTurns = maxTurns,
            }, cancellationToken);

        await _broadcaster.ListUpdated(listId);
    }

    [McpServerTool, Description("Set per-task config overrides (model/system prompt/agent path/max turns). Pass null for any field to clear that override.")]
    public async Task SetTaskConfig(
        string taskId, string? model, string? systemPrompt, string? agentPath, int? maxTurns, CancellationToken cancellationToken)
    {
        _ = await _tasks.GetByIdAsync(taskId, cancellationToken)
            ?? throw new InvalidOperationException($"Task {taskId} not found.");

        await _tasks.UpdateAgentSettingsAsync(taskId, model.NullIfBlank(), systemPrompt.NullIfBlank(), agentPath.NullIfBlank(), maxTurns, ct: cancellationToken);
        await _broadcaster.TaskUpdated(taskId);
    }

    [McpServerTool, Description("Get per-task config overrides (model/system prompt/agent path/max turns). Returns null if no override is set on this task.")]
    public async Task<TaskConfigDto?> GetTaskConfig(string taskId, CancellationToken cancellationToken)
    {
        var task = await _tasks.GetByIdAsync(taskId, cancellationToken)
            ?? throw new InvalidOperationException($"Task {taskId} not found.");
        if (task.Model is null && task.SystemPrompt is null && task.AgentPath is null && task.MaxTurns is null)
            return null;
        return new TaskConfigDto(task.Model, task.SystemPrompt, task.AgentPath, task.MaxTurns);
    }
}
