/**
 * PugBrain tool definitions for OpenClaw.
 *
 * Each tool proxies to the MCP server via JSON-RPC.
 *
 * Uses raw JSON Schema for parameters. Provider compatibility notes:
 *   - `additionalProperties: false` required by OpenAI strict mode
 *   - `number` instead of `integer` for Gemini compatibility
 *   - No `maxLength`/`maxItems`/`minimum`/`maximum` — some providers
 *     reject schemas with constraint keywords; our MCP server validates
 *
 * Registers 6 core tools:
 *   pugbrain_remember  — Store a memory
 *   pugbrain_recall    — Query/search memories
 *   pugbrain_context   — Get recent context
 *   pugbrain_todo      — Quick TODO shortcut
 *   pugbrain_stats     — Brain statistics
 *   pugbrain_health    — Brain health diagnostics
 */

import type { PugBrainMcpClient } from "./mcp-client.js";

// ── Types ──────────────────────────────────────────────────

type JsonSchema = {
  readonly type: "object";
  readonly properties: Record<string, unknown>;
  readonly required?: readonly string[];
  readonly additionalProperties?: boolean;
};

export type ToolDefinition = {
  readonly name: string;
  readonly description: string;
  readonly parameters: JsonSchema;
  readonly execute: (id: string, args: Record<string, unknown>) => Promise<unknown>;
};

// ── Tool factory ───────────────────────────────────────────

export function createTools(mcp: PugBrainMcpClient): ToolDefinition[] {
  const call = async (
    toolName: string,
    args: Record<string, unknown>,
  ): Promise<unknown> => {
    if (!mcp.connected) {
      try {
        await mcp.ensureConnected();
      } catch (err) {
        return {
          error: true,
          message: `PugBrain auto-connect failed: ${(err as Error).message}`,
        };
      }
    }

    try {
      const raw = await mcp.callTool(toolName, args);
      try {
        return JSON.parse(raw);
      } catch {
        return { text: raw };
      }
    } catch (err) {
      return {
        error: true,
        message: `Tool ${toolName} failed: ${(err as Error).message}`,
      };
    }
  };

  return [
    {
      name: "pugbrain_remember",
      description:
        "Store a memory in PugBrain. Use this to remember facts, decisions, " +
        "insights, todos, errors, and other information that should persist across sessions.",
      parameters: {
        type: "object",
        properties: {
          content: {
            type: "string",
            description: "The content to remember",
          },
          type: {
            type: "string",
            enum: [
              "fact",
              "decision",
              "preference",
              "todo",
              "insight",
              "context",
              "instruction",
              "error",
              "workflow",
              "reference",
            ],
            description: "Memory type (auto-detected if not specified)",
          },
          priority: {
            type: "number",
            description: "Priority 0-10 (5=normal, 10=critical)",
          },
          tags: {
            type: "array",
            items: { type: "string" },
            description: "Tags for categorization",
          },
          expires_days: {
            type: "number",
            description: "Days until memory expires (1-3650)",
          },
        },
        required: ["content"],
        additionalProperties: false,
      },
      execute: (_id, args) => call("pugbrain_remember", args),
    },

    {
      name: "pugbrain_recall",
      description:
        "Query memories from PugBrain. Use this to recall past information, " +
        "decisions, patterns, or context relevant to the current task.",
      parameters: {
        type: "object",
        properties: {
          query: {
            type: "string",
            description: "The query to search memories",
          },
          depth: {
            type: "number",
            description:
              "Search depth: 0=instant, 1=context, 2=habit, 3=deep",
          },
          max_tokens: {
            type: "number",
            description: "Maximum tokens in response (default: 500)",
          },
          min_confidence: {
            type: "number",
            description: "Minimum confidence threshold (0-1)",
          },
        },
        required: ["query"],
        additionalProperties: false,
      },
      execute: (_id, args) => call("pugbrain_recall", args),
    },

    {
      name: "pugbrain_context",
      description:
        "Get recent context from PugBrain. Use this at the start of " +
        "tasks to inject relevant recent memories.",
      parameters: {
        type: "object",
        properties: {
          limit: {
            type: "number",
            description: "Number of recent memories (default: 10, max: 200)",
          },
          fresh_only: {
            type: "boolean",
            description: "Only include memories less than 30 days old",
          },
        },
        additionalProperties: false,
      },
      execute: (_id, args) => call("pugbrain_context", args),
    },

    {
      name: "pugbrain_todo",
      description:
        "Quick shortcut to add a TODO memory with 30-day expiry.",
      parameters: {
        type: "object",
        properties: {
          task: {
            type: "string",
            description: "The task to remember",
          },
          priority: {
            type: "number",
            description: "Priority 0-10 (default: 5)",
          },
        },
        required: ["task"],
        additionalProperties: false,
      },
      execute: (_id, args) => call("pugbrain_todo", args),
    },

    {
      name: "pugbrain_stats",
      description:
        "Get brain statistics including memory counts and freshness.",
      parameters: {
        type: "object",
        properties: {},
        additionalProperties: false,
      },
      execute: (_id, args) => call("pugbrain_stats", args),
    },

    {
      name: "pugbrain_health",
      description:
        "Get brain health diagnostics including grade, purity score, " +
        "and recommendations.",
      parameters: {
        type: "object",
        properties: {},
        additionalProperties: false,
      },
      execute: (_id, args) => call("pugbrain_health", args),
    },
  ];
}
