/**
 * Slack native MCP server (https://mcp.slack.com/mcp).
 *
 * Registers Slack's official remote MCP server as an `http` MCP so the agent can
 * search/read/send/react and work with canvases through Slack's own tools —
 * instead of nomos's in-process Slack Web API tools. Mirrors the Google official
 * remote-MCP pattern in `src/sdk/google-mcp.ts`.
 *
 * Gating (backend "mcp" vs "tools") is the caller's job (agent-runtime / CLI read
 * `config.slackBackend`); this module just builds the server when a token exists.
 * Auth is a Slack OAuth *user* token passed as a Bearer header — see
 * `src/auth/slack-oauth.ts`. Returns `{}` (agent gets no Slack tools) when no
 * token is connected.
 */

import type { McpServerConfig } from "@anthropic-ai/claude-agent-sdk";
import { createLogger } from "../lib/logger.ts";
import { getSlackMcpToken } from "../auth/slack-oauth.ts";

const log = createLogger("slack-native-mcp");

/**
 * Build the native Slack MCP server for a user. Empty `{}` when no OAuth token is
 * connected (the caller should have already decided backend === "mcp"). The
 * server is keyed `slack`, so tools appear as `mcp__slack__<tool>`.
 */
export async function buildSlackNativeMcpServers(
  userId: string,
): Promise<Record<string, McpServerConfig>> {
  const token = await getSlackMcpToken(userId);
  if (!token) {
    log.warn(
      { userId },
      "Slack native MCP backend selected but no OAuth token — connect via `nomos slack connect-mcp` or set SLACK_MCP_USER_TOKEN",
    );
    return {};
  }
  // Register mcp.slack.com through the persistent in-process PROXY, not as a raw
  // remote `http` server. The SDK cold-connects remote servers per turn and
  // can't wait for them, so a raw http config leaves mcp.slack.com "pending" at
  // turn start (~2-3s handshake) and its tools miss the tool list. The proxy
  // keeps a warm connection and exposes the tools in-process (present at turn
  // start). See src/sdk/slack-mcp-proxy.ts.
  const { buildSlackMcpProxyServer } = await import("./slack-mcp-proxy.ts");
  const servers = await buildSlackMcpProxyServer(token);
  log.info({ userId }, "registered Slack native MCP server (persistent proxy)");
  return servers;
}

/**
 * System-prompt section asserting the user's Slack access, so the agent stops
 * hunting for / hallucinating Slack tools. Mirrors `buildGoogleIntegrationPrompt`.
 */
export function buildSlackIntegrationPrompt(hasServer: boolean): string {
  if (!hasServer) {
    return [
      "## Slack: not connected",
      "Slack is **not connected** for this user — you currently have NO Slack tools.",
      "Do NOT say Slack tools are loading, and do NOT invent a workaround. If the user asks for something that needs Slack, tell them to connect it (Settings → Slack, or `nomos slack connect-mcp`) and stop.",
    ].join("\n");
  }
  return [
    "## Slack (native MCP)",
    "You have **active, authenticated** Slack access **right now** through Slack's official MCP server. Use the `mcp__slack__*` tools to search messages/channels/users/files, read channels and threads, send messages, add reactions, and read/write canvases.",
    "NEVER tell the user Slack is 'connecting', 'loading', 'being set up', or 'will be available in a moment' — the tools are ready. Just call them. If a specific call fails, report the ACTUAL error (e.g. an auth/permission error means the token needs reconnecting) rather than claiming the connection is still initializing.",
    "The `slack` skill routes Slack work; its sub-skills (`slack-channel-summarization`, `slack-daily-digest`, `slack-notification-triage`, `slack-outgoing-message`, `slack-reply-drafting`) give workflow guidance.",
    'Respect the user\'s message-consent settings: draft for approval unless the user explicitly says to post/send. Do a fresh read before resolving relative targets like "the last message", and call out high-impact posts (channel-wide pings, customer-facing) before sending.',
  ].join("\n");
}
