package todoist

import (
	"slices"

	"github.com/tidbcloud/AgentTeam/internal/extension/registry"
	"github.com/tidbcloud/AgentTeam/internal/extension/spec"
)

// Action name constants for the Todoist catalog.
const (
	ActionGetCurrentUser = "get-current-user"
	ActionListProjects   = "list-projects"
	ActionGetProject     = "get-project"
	ActionCreateProject  = "create-project"
	ActionUpdateProject  = "update-project"
	ActionListSections   = "list-sections"
	ActionGetSection     = "get-section"
	ActionCreateSection  = "create-section"
	ActionUpdateSection  = "update-section"
	ActionListTasks      = "list-tasks"
	ActionGetTask        = "get-task"
	ActionCreateTask     = "create-task"
	ActionUpdateTask     = "update-task"
	ActionCloseTask      = "close-task"
	ActionListComments   = "list-comments"
	ActionGetComment     = "get-comment"
	ActionCreateComment  = "create-comment"
	ActionUpdateComment  = "update-comment"
	ActionListLabels     = "list-labels"
)

// Definition returns the Agent-visible Todoist catalog, assembled from the
// per-resource action groups below.
func Definition() registry.Definition {
	return registry.Definition{
		Domain:      Domain,
		Version:     1,
		Name:        "Todoist",
		Description: "Manage Todoist projects, sections, tasks, comments, and labels with the connected account.",
		Actions: slices.Concat(
			projectActions(),
			sectionActions(),
			taskActions(),
			commentActions(),
			labelActions(),
		),
	}
}

func projectActions() []registry.DefinitionAction {
	return []registry.DefinitionAction{
		{
			Name:        ActionGetCurrentUser,
			Summary:     "Get the current Todoist user",
			Description: "Get the current Todoist user profile.",
			Safety:      readSafety(),
			InputSchema: noInputSchema(),
			OutputSchema: objectSchema(map[string]any{
				"user": rawObjectSchema("The Todoist user object."),
			}, []string{"user"}),
			Example: map[string]any{},
		},
		{
			Name:        ActionListProjects,
			Summary:     "List Todoist projects",
			Description: "List Todoist projects visible to the connected account.",
			Safety:      readSafety(),
			InputSchema: listProjectsInputSchema(),
			OutputSchema: paginatedSchema(
				"projects", "A Todoist project.",
				"The Todoist projects returned for the page."),
			Example: map[string]any{"limit": 50},
		},
		{
			Name:        ActionGetProject,
			Summary:     "Get a Todoist project",
			Description: "Get one Todoist project by ID.",
			Safety:      readSafety(),
			InputSchema: objectSchema(map[string]any{
				"projectId": nonEmptyStringSchema("Todoist project ID."),
			}, []string{"projectId"}),
			OutputSchema: objectSchema(map[string]any{
				"project": rawObjectSchema("The Todoist project object."),
			}, []string{"project"}),
			Example: map[string]any{"projectId": "6XG7QmG5vQMC"},
		},
		{
			Name:        ActionCreateProject,
			Summary:     "Create a Todoist project",
			Description: "Create a Todoist project.",
			Safety:      writeSafety(),
			InputSchema: createProjectInputSchema(),
			OutputSchema: objectSchema(map[string]any{
				"project": rawObjectSchema("The created Todoist project object."),
			}, []string{"project"}),
			Example: map[string]any{"name": "AgentTeam integrations"},
		},
		{
			Name:        ActionUpdateProject,
			Summary:     "Update a Todoist project",
			Description: "Update a Todoist project.",
			Safety:      writeSafety(),
			InputSchema: updateProjectInputSchema(),
			OutputSchema: objectSchema(map[string]any{
				"project": rawObjectSchema("The updated Todoist project object."),
			}, []string{"project"}),
			Example: map[string]any{"projectId": "6XG7QmG5vQMC", "name": "Renamed"},
		},
	}
}

func sectionActions() []registry.DefinitionAction {
	return []registry.DefinitionAction{
		{
			Name:        ActionListSections,
			Summary:     "List Todoist sections",
			Description: "List Todoist sections, optionally scoped to a project.",
			Safety:      readSafety(),
			InputSchema: listSectionsInputSchema(),
			OutputSchema: paginatedSchema(
				"sections", "A Todoist section.",
				"The Todoist sections returned for the page."),
			Example: map[string]any{"limit": 50},
		},
		{
			Name:        ActionGetSection,
			Summary:     "Get a Todoist section",
			Description: "Get one Todoist section by ID.",
			Safety:      readSafety(),
			InputSchema: objectSchema(map[string]any{
				"sectionId": nonEmptyStringSchema("Todoist section ID."),
			}, []string{"sectionId"}),
			OutputSchema: objectSchema(map[string]any{
				"section": rawObjectSchema("The Todoist section object."),
			}, []string{"section"}),
			Example: map[string]any{"sectionId": "12345"},
		},
		{
			Name:        ActionCreateSection,
			Summary:     "Create a Todoist section",
			Description: "Create a Todoist section.",
			Safety:      writeSafety(),
			InputSchema: createSectionInputSchema(),
			OutputSchema: objectSchema(map[string]any{
				"section": rawObjectSchema("The created Todoist section object."),
			}, []string{"section"}),
			Example: map[string]any{"projectId": "6XG7QmG5vQMC", "name": "In progress"},
		},
		{
			Name:        ActionUpdateSection,
			Summary:     "Update a Todoist section",
			Description: "Update a Todoist section.",
			Safety:      writeSafety(),
			InputSchema: updateSectionInputSchema(),
			OutputSchema: objectSchema(map[string]any{
				"section": rawObjectSchema("The updated Todoist section object."),
			}, []string{"section"}),
			Example: map[string]any{"sectionId": "12345", "name": "Renamed"},
		},
	}
}

func taskActions() []registry.DefinitionAction {
	return []registry.DefinitionAction{
		{
			Name:        ActionListTasks,
			Summary:     "List Todoist tasks",
			Description: "List Todoist tasks using the API v1 filters.",
			Safety:      readSafety(),
			InputSchema: listTasksInputSchema(),
			OutputSchema: paginatedSchema(
				"tasks", "A Todoist task.",
				"The Todoist tasks returned for the page."),
			Example: map[string]any{"projectId": "6XG7QmG5vQMC", "limit": 50},
		},
		{
			Name:        ActionGetTask,
			Summary:     "Get a Todoist task",
			Description: "Get one Todoist task by ID.",
			Safety:      readSafety(),
			InputSchema: objectSchema(map[string]any{
				"taskId": nonEmptyStringSchema("Todoist task ID."),
			}, []string{"taskId"}),
			OutputSchema: objectSchema(map[string]any{
				"task": rawObjectSchema("The Todoist task object."),
			}, []string{"task"}),
			Example: map[string]any{"taskId": "7890123456"},
		},
		{
			Name:        ActionCreateTask,
			Summary:     "Create a Todoist task",
			Description: "Create a Todoist task.",
			Safety:      writeSafety(),
			InputSchema: createTaskInputSchema(),
			OutputSchema: objectSchema(map[string]any{
				"task": rawObjectSchema("The created Todoist task object."),
			}, []string{"task"}),
			Example: map[string]any{
				"content":   "Review the provider migration PR",
				"projectId": "6XG7QmG5vQMC",
				"dueString": "tomorrow 10am",
				"priority":  3,
			},
		},
		{
			Name:        ActionUpdateTask,
			Summary:     "Update a Todoist task",
			Description: "Update a Todoist task.",
			Safety:      writeSafety(),
			InputSchema: updateTaskInputSchema(),
			OutputSchema: objectSchema(map[string]any{
				"task": rawObjectSchema("The updated Todoist task object."),
			}, []string{"task"}),
			Example: map[string]any{"taskId": "7890123456", "content": "Updated title"},
		},
		{
			Name:        ActionCloseTask,
			Summary:     "Close a Todoist task",
			Description: "Close (complete) a Todoist task.",
			Safety:      writeSafety(),
			InputSchema: objectSchema(map[string]any{
				"taskId": nonEmptyStringSchema("Todoist task ID."),
			}, []string{"taskId"}),
			OutputSchema: objectSchema(map[string]any{
				"success": literalTrueSchema(),
			}, []string{"success"}),
			Example: map[string]any{"taskId": "7890123456"},
		},
	}
}

func commentActions() []registry.DefinitionAction {
	return []registry.DefinitionAction{
		{
			Name:        ActionListComments,
			Summary:     "List Todoist comments",
			Description: "List Todoist comments by task or project.",
			Safety:      readSafety(),
			InputSchema: listCommentsInputSchema(),
			OutputSchema: paginatedSchema(
				"comments", "A Todoist comment.",
				"The Todoist comments returned for the page."),
			Example: map[string]any{"taskId": "7890123456"},
		},
		{
			Name:        ActionGetComment,
			Summary:     "Get a Todoist comment",
			Description: "Get one Todoist comment by ID.",
			Safety:      readSafety(),
			InputSchema: objectSchema(map[string]any{
				"commentId": nonEmptyStringSchema("Todoist comment ID."),
			}, []string{"commentId"}),
			OutputSchema: objectSchema(map[string]any{
				"comment": rawObjectSchema("The Todoist comment object."),
			}, []string{"comment"}),
			Example: map[string]any{"commentId": "4567890"},
		},
		{
			Name:        ActionCreateComment,
			Summary:     "Create a Todoist comment",
			Description: "Create a Todoist comment on a task or project.",
			Safety:      writeSafety(),
			InputSchema: createCommentInputSchema(),
			OutputSchema: objectSchema(map[string]any{
				"comment": rawObjectSchema("The created Todoist comment object."),
			}, []string{"comment"}),
			Example: map[string]any{
				"content": "Investigated; fix incoming.",
				"taskId":  "7890123456",
			},
		},
		{
			Name:        ActionUpdateComment,
			Summary:     "Update a Todoist comment",
			Description: "Update the content of one Todoist comment.",
			Safety:      writeSafety(),
			InputSchema: objectSchema(map[string]any{
				"commentId": nonEmptyStringSchema("Todoist comment ID."),
				"content":   nonEmptyStringSchema("Updated Todoist comment content."),
			}, []string{"commentId", "content"}),
			OutputSchema: objectSchema(map[string]any{
				"comment": rawObjectSchema("The updated Todoist comment object."),
			}, []string{"comment"}),
			Example: map[string]any{"commentId": "4567890", "content": "Edited"},
		},
	}
}

func labelActions() []registry.DefinitionAction {
	return []registry.DefinitionAction{
		{
			Name:        ActionListLabels,
			Summary:     "List Todoist labels",
			Description: "List Todoist labels visible to the connected account.",
			Safety:      readSafety(),
			InputSchema: listLabelsInputSchema(),
			OutputSchema: paginatedSchema(
				"labels", "A Todoist label.",
				"The Todoist labels returned for the page."),
			Example: map[string]any{"limit": 50},
		},
	}
}

func readSafety() spec.Safety {
	return spec.Safety{Class: "read", Idempotent: true, Destructive: false}
}

func writeSafety() spec.Safety {
	return spec.Safety{Class: "mutation", Idempotent: false, Destructive: false}
}
