/**
 * RecallNest + Claude Agent SDK — Minimal Example
 *
 * A Claude agent with persistent memory powered by RecallNest HTTP API.
 *
 * Prerequisites:
 *   1. RecallNest API server running: bun run api  (port 4318)
 *   2. ANTHROPIC_API_KEY set in environment
 *   3. Install deps: bun add @anthropic-ai/sdk
 *
 * Run: bun run integrations/examples/claude-agent-sdk/memory-agent.ts
 */

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();
const RECALLNEST = "http://localhost:4318";

function buildRecallContext() {
  const sessionId = process.env.RECALLNEST_SESSION_ID;
  const scope = process.env.RECALLNEST_SCOPE;
  const resolvedScope = scope || (sessionId ? `session:${sessionId}` : undefined);
  return {
    ...(sessionId ? { sessionId } : {}),
    ...(resolvedScope ? { scope: resolvedScope } : {}),
  };
}

// --- Tool definitions for Claude ---

const tools: Anthropic.Tool[] = [
  {
    name: "recall_memory",
    description:
      "Recall relevant memories from past conversations. Use at the start of every task.",
    input_schema: {
      type: "object" as const,
      properties: {
        query: {
          type: "string",
          description: "Search query — use 2-3 key nouns",
        },
      },
      required: ["query"],
    },
  },
  {
    name: "store_memory",
    description:
      "Store an important fact, decision, or preference for future recall.",
    input_schema: {
      type: "object" as const,
      properties: {
        text: {
          type: "string",
          description: "The memory content to store",
        },
        category: {
          type: "string",
          enum: [
            "profile",
            "preferences",
            "entities",
            "events",
            "cases",
            "patterns",
          ],
          description: "Memory category",
        },
      },
      required: ["text"],
    },
  },
];

// --- Tool handler: calls RecallNest HTTP API ---

async function handleTool(
  name: string,
  input: Record<string, unknown>
): Promise<string> {
  if (name === "recall_memory") {
    const res = await fetch(`${RECALLNEST}/v1/auto-recall`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ message: input.query, limit: 5, ...buildRecallContext() }),
    });
    if (!res.ok) return `Error: ${res.status} ${await res.text()}`;
    const data = await res.json();
    return JSON.stringify({
      mode: data.mode,
      resolvedScope: data.resolvedScope,
      summary: data.resume?.summary,
      stableContext: data.resume?.stableContext || [],
      results: data.results || [],
      searchSkippedReason: data.searchSkippedReason,
    }, null, 2);
  }

  if (name === "store_memory") {
    const recallContext = buildRecallContext();
    if (!("scope" in recallContext)) {
      return "Set RECALLNEST_SCOPE or RECALLNEST_SESSION_ID before storing durable memory.";
    }
    const res = await fetch(`${RECALLNEST}/v1/store`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        text: input.text,
        category: input.category || "events",
        scope: recallContext.scope,
        source: "claude-agent-sdk-example",
      }),
    });
    if (!res.ok) return `Error: ${res.status} ${await res.text()}`;
    return "Memory stored successfully.";
  }

  return `Unknown tool: ${name}`;
}

// --- Agent loop ---

async function runAgent(userMessage: string) {
  console.log(`\nUser: ${userMessage}\n`);

  const messages: Anthropic.MessageParam[] = [
    { role: "user", content: userMessage },
  ];

  // Agentic loop: keep going until no more tool calls
  while (true) {
    const response = await client.messages.create({
      model: "claude-sonnet-4-20250514",
      max_tokens: 1024,
      system:
        "You are a helpful assistant with persistent memory. " +
        "Always use recall_memory at the start of a task or project pivot to recover relevant context. " +
        "Store important facts with store_memory.",
      tools,
      messages,
    });

    // Collect text output
    for (const block of response.content) {
      if (block.type === "text") {
        console.log(`Assistant: ${block.text}`);
      }
    }

    // If no tool use, we're done
    if (response.stop_reason !== "tool_use") break;

    // Handle tool calls
    const toolUseBlocks = response.content.filter(
      (b): b is Anthropic.ContentBlockParam & { type: "tool_use"; id: string; name: string; input: Record<string, unknown> } =>
        b.type === "tool_use"
    );

    // Add assistant response to history
    messages.push({ role: "assistant", content: response.content });

    // Process each tool call and add results
    const toolResults: Anthropic.ToolResultBlockParam[] = [];
    for (const toolUse of toolUseBlocks) {
      console.log(`  [Tool] ${toolUse.name}(${JSON.stringify(toolUse.input)})`);
      const result = await handleTool(toolUse.name, toolUse.input);
      toolResults.push({
        type: "tool_result",
        tool_use_id: toolUse.id,
        content: result,
      });
    }

    messages.push({ role: "user", content: toolResults });
  }
}

// --- Main ---

const query = process.argv[2] || "What do you remember about my Docker setup?";
runAgent(query);
