/**
 * Source catalog for the now/check agent.
 *
 * The catalog (ALL_SOURCES) is fixed code — each source needs a prompt
 * hint and tool-prefix mapping. Which sources are *active* is user-
 * editable via the Settings modal; see server/lib/settings.ts.
 */

import { USER_PROJECT_KEY } from "./paths";

export type SourceId = "linear" | "notion" | "posthog" | "m365" | "files" | "chats";

export type SourceDef = {
  id: SourceId;
  label: string;       // shown in the UI ("Linear", "Notion", etc.)
  promptHint: string;  // line included in the agent prompt
  /** Tool name prefixes the agent actually calls — used to map back from
   *  tool_use names to which source we credit. */
  toolPrefixes: string[];
};

export const ALL_SOURCES: Record<SourceId, SourceDef> = {
  linear: {
    id: "linear",
    label: "Linear",
    promptHint:
      "- Linear MCP — ONLY the AWS team in the TCMC workspace " +
      "(team key \"AWS\", URL https://linear.app/tcmc/team/AWS/). " +
      "When calling mcp__claude_ai_Linear__list_issues / list_projects / list_cycles, " +
      "always pass team=\"AWS\". Ignore Backend / Frontend / QA / other WeTransact teams. " +
      "Also call mcp__claude_ai_Linear__list_comments on recent issues (last 14 days) and " +
      "surface any comment that @-mentions Pavel (matches \"@pavel\", \"@pavel.racu\", or " +
      "Pavel Racu's Linear userId — use mcp__claude_ai_Linear__list_users once to resolve " +
      "the id, then filter). Treat these as the highest-priority threads: someone is " +
      "explicitly waiting on Pavel's input.",
    toolPrefixes: ["mcp__claude_ai_Linear__"],
  },
  notion: {
    id: "notion",
    label: "Notion",
    promptHint: "- Notion MCP — docs/decisions (notion-search, notion-fetch)",
    toolPrefixes: ["mcp__claude_ai_Notion__"],
  },
  posthog: {
    id: "posthog",
    label: "PostHog",
    promptHint: "- PostHog MCP — product metric / feature flag / insight changes",
    toolPrefixes: ["mcp__plugin_posthog_posthog__"],
  },
  m365: {
    id: "m365",
    label: "Outlook + Teams",
    promptHint: "- Microsoft 365 MCP — outlook_email_search for replies, chat_message_search for Teams threads",
    toolPrefixes: ["mcp__claude_ai_Microsoft_365__"],
  },
  files: {
    id: "files",
    label: "claude-output",
    promptHint: "- Read recent files in ~/Library/Mobile Documents/com~apple~CloudDocs/claude-output/ (Glob + Read; check mtime within last 14d)",
    toolPrefixes: ["Read", "Glob"],
  },
  chats: {
    id: "chats",
    label: "Recent chats",
    promptHint: `- Bash (grep) on ~/.claude/projects/${USER_PROJECT_KEY}/*.jsonl for recent chat mentions of the topic (last 7 days only)`,
    toolPrefixes: ["Bash", "Grep"],
  },
};

/** Settings.ts injects the active-sources reader at startup to break the
 *  import cycle (settings.ts imports SourceId/ALL_SOURCES from this file). */
let activeSourcesReader: () => SourceId[] = () => ["linear", "notion", "files", "chats"];
export function setActiveSourcesReader(fn: () => SourceId[]) {
  activeSourcesReader = fn;
}

/** Render the active source list as a markdown bullet list for the prompt. */
export function activeSourcesPromptBlock(): string {
  return activeSourcesReader().map((id) => ALL_SOURCES[id].promptHint).join("\n");
}

/** Map a tool name (from a tool_use event) to a SourceId, if any. */
export function classifyTool(toolName: string): SourceId | null {
  for (const id of Object.keys(ALL_SOURCES) as SourceId[]) {
    const def = ALL_SOURCES[id];
    if (def.toolPrefixes.some((p) => toolName === p || toolName.startsWith(p))) {
      return id;
    }
  }
  return null;
}

/** Distinct ordered list of sources the agent actually used in a check run. */
export function sourcesUsed(toolNames: string[]): SourceId[] {
  const seen = new Set<SourceId>();
  const out: SourceId[] = [];
  for (const name of toolNames) {
    const src = classifyTool(name);
    if (src && !seen.has(src)) {
      seen.add(src);
      out.push(src);
    }
  }
  return out;
}
