package hackernews

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

// Action name constants for the Hacker News catalog (lowercase kebab-case per
// the registry catalog contract; upstream names are snake_case).
const (
	ActionGetAskStories     = "get-ask-stories"
	ActionGetBestStories    = "get-best-stories"
	ActionGetItem           = "get-item"
	ActionGetItemWithID     = "get-item-with-id"
	ActionGetJobStories     = "get-job-stories"
	ActionGetLatestPosts    = "get-latest-posts"
	ActionGetMaxItemID      = "get-max-item-id"
	ActionGetNewStories     = "get-new-stories"
	ActionGetShowStories    = "get-show-stories"
	ActionGetTopStories     = "get-top-stories"
	ActionGetUpdates        = "get-updates"
	ActionGetUser           = "get-user"
	ActionGetUserByUsername = "get-user-by-username"
	ActionSearchPosts       = "search-posts"
)

// Definition returns the Agent-visible Hacker News catalog: all 14 upstream
// actions in name-sorted order. Every Action is a read against one of the two
// public APIs; input and output property names keep the upstream wire names
// verbatim.
func Definition() registry.Definition {
	return registry.Definition{
		Domain:      Domain,
		Version:     1,
		Name:        "Hacker News",
		Description: "Read Hacker News items, nested comment trees, users, updates, story feeds, and search results through the public Firebase and Algolia APIs.",
		Actions: []registry.DefinitionAction{
			storyFeedAction(ActionGetAskStories,
				"Get the latest Ask HN story IDs",
				"Get the latest Ask HN story IDs from Hacker News.",
				false),
			storyFeedAction(ActionGetBestStories,
				"Get the best Hacker News story IDs",
				"Get the best story IDs from Hacker News ranked by score.",
				true),
			{
				Name:        ActionGetItem,
				Summary:     "Get a Hacker News item",
				Description: "Get a Hacker News item by its numeric ID.",
				Safety:      readSafety(),
				InputSchema: getItemInputSchema(),
				OutputSchema: nullableSchema(
					firebaseItemOutputSchema()),
				Example: map[string]any{"id": 8863},
			},
			{
				Name:         ActionGetItemWithID,
				Summary:      "Get a Hacker News item with its comment tree",
				Description:  "Get a Hacker News item with a bounded nested comment tree.",
				Safety:       readSafety(),
				InputSchema:  getItemWithIDInputSchema(),
				OutputSchema: nestedItemOutputSchema(),
				Example: map[string]any{
					"item_id":       "8863",
					"max_depth":     2,
					"max_children":  10,
					"truncate_text": true,
				},
			},
			storyFeedAction(ActionGetJobStories,
				"Get the latest Hacker News job story IDs",
				"Get the latest job story IDs from Hacker News.",
				false),
			{
				Name:        ActionGetLatestPosts,
				Summary:     "Get the latest Hacker News posts",
				Description: "Get the latest Hacker News posts via Algolia search_by_date.",
				Safety:      readSafety(),
				InputSchema: searchInputSchema(false),
				OutputSchema: searchOutputSchema(
					"The latest posts, passed through from the Algolia search envelope."),
				Example: map[string]any{"page": 0, "size": 5, "tags": []string{"story"}},
			},
			{
				Name:         ActionGetMaxItemID,
				Summary:      "Get the largest Hacker News item ID",
				Description:  "Get the current largest Hacker News item ID.",
				Safety:       readSafety(),
				InputSchema:  prettyInputSchema(),
				OutputSchema: maxItemIDOutputSchema(),
				Example:      map[string]any{},
			},
			storyFeedAction(ActionGetNewStories,
				"Get the newest Hacker News story IDs",
				"Get the newest story IDs from Hacker News.",
				true),
			storyFeedAction(ActionGetShowStories,
				"Get the latest Show HN story IDs",
				"Get the latest Show HN story IDs from Hacker News.",
				false),
			storyFeedAction(ActionGetTopStories,
				"Get the top Hacker News story IDs",
				"Get the top story IDs from Hacker News sorted by front page position.",
				true),
			{
				Name:         ActionGetUpdates,
				Summary:      "Get changed Hacker News items and profiles",
				Description:  "Get recently changed items and user profiles from Hacker News.",
				Safety:       readSafety(),
				InputSchema:  prettyInputSchema(),
				OutputSchema: updatesOutputSchema(),
				Example:      map[string]any{},
			},
			{
				Name:        ActionGetUser,
				Summary:     "Get a Hacker News user summary",
				Description: "Get a Hacker News user's public profile summary by username.",
				Safety:      readSafety(),
				InputSchema: usernameInputSchema(),
				OutputSchema: nullableSchema(
					userSummaryOutputSchema()),
				Example: map[string]any{"username": "pg"},
			},
			{
				Name:        ActionGetUserByUsername,
				Summary:     "Get a Hacker News user profile",
				Description: "Get a Hacker News user's detailed public profile by username.",
				Safety:      readSafety(),
				InputSchema: usernameInputSchema(),
				OutputSchema: nullableSchema(
					userDetailOutputSchema()),
				Example: map[string]any{"username": "pg"},
			},
			{
				Name:        ActionSearchPosts,
				Summary:     "Search Hacker News posts",
				Description: "Search Hacker News posts using Algolia full-text search.",
				Safety:      readSafety(),
				InputSchema: searchInputSchema(true),
				OutputSchema: searchOutputSchema(
					"The search result hits, passed through from the Algolia search envelope."),
				Example: map[string]any{"query": "show hn", "page": 0, "size": 5},
			},
		},
	}
}

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

// storyFeedAction builds one of the six Firebase story-feed read Actions:
// shared pretty input, shared story-ids output shape, and a per-feed summary.
func storyFeedAction(action, summary, description string, includeCount bool) registry.DefinitionAction {
	return registry.DefinitionAction{
		Name:         action,
		Summary:      summary,
		Description:  description,
		Safety:       readSafety(),
		InputSchema:  prettyInputSchema(),
		OutputSchema: storyIDsOutputSchema(includeCount),
		Example:      map[string]any{},
	}
}
