import type { ToolDef } from '../llm/openai-compat.js';

// serverId is our own slug (lowercase). Tool names come from the remote MCP
// server and commonly use camelCase (e.g. NocoDB's `createRecords`), so they
// must allow uppercase — the combined `mcp__id__name` still matches the LLM
// tool-name grammar `[a-zA-Z0-9_-]`.
const SLUG = /^[a-z0-9_-]{1,64}$/;
const TOOL_NAME = /^[a-zA-Z0-9_-]{1,64}$/;

export function normalizeToolName(serverId: string, toolName: string): string {
  return `mcp__${serverId}__${toolName}`;
}

export function parseToolName(name: string): { serverId: string; toolName: string } | null {
  if (!name.startsWith('mcp__')) return null;
  const parts = name.split('__');
  if (parts.length !== 3) return null;
  const [, serverId, toolName] = parts;
  if (!SLUG.test(serverId) || !TOOL_NAME.test(toolName)) return null;
  return { serverId, toolName };
}

export function matchesAnyPattern(name: string, patterns: string[]): boolean {
  return patterns.some((p) => {
    if (p === name) return true;
    if (p.endsWith('__*')) {
      const prefix = p.slice(0, -1);
      return name.startsWith(prefix) && name.length > prefix.length;
    }
    return false;
  });
}

export interface CachedTool {
  serverId: string;
  toolName: string;
  description: string | null;
  inputSchema: string | null;
}

const MAX_DESCRIPTION = 1000;

export function buildToolDefsFromCache(
  cache: CachedTool[],
  patterns: string[],
  serverNames: Map<string, string>,
): ToolDef[] {
  const mcpPatterns = patterns.filter((p) => p.startsWith('mcp__'));
  if (mcpPatterns.length === 0) return [];

  const defs: ToolDef[] = [];
  for (const tool of cache) {
    if (!SLUG.test(tool.serverId) || !TOOL_NAME.test(tool.toolName)) continue;
    const canonical = normalizeToolName(tool.serverId, tool.toolName);
    if (!matchesAnyPattern(canonical, mcpPatterns)) continue;

    let params: unknown = { type: 'object', properties: {} };
    if (tool.inputSchema) {
      try {
        params = JSON.parse(tool.inputSchema);
      } catch {
        // Keep default object schema
      }
    }

    const serverLabel = serverNames.get(tool.serverId) ?? tool.serverId;
    const rawDesc = tool.description ?? '';
    const description = `[外部ツール: ${serverLabel} 提供] ${rawDesc}`.slice(0, MAX_DESCRIPTION);

    defs.push({
      type: 'function',
      function: {
        name: canonical,
        description,
        parameters: params as Record<string, unknown>,
      },
    });
  }
  return defs;
}
