import type { Tool, ToolResult } from '../types.js';
import type { MemoryStore } from '../../memory/store.js';
import type { HybridSearch } from '../../memory/hybrid-search.js';

interface MemorySearchArgs {
  query: string;
}

/**
 * Creates a memory.search tool bound to the given MemoryStore instance.
 * When a HybridSearch instance is provided, uses vector + keyword search;
 * otherwise falls back to keyword-only search.
 */
export function createMemorySearchTool(store: MemoryStore, hybridSearch?: HybridSearch): Tool {
  return {
    name: 'memory.search',
    description:
      'Search across all memory files for a keyword or phrase. Returns matching lines with surrounding context from every namespace.' +
      (hybridSearch ? ' Uses semantic vector search combined with keyword matching for better results.' : '') +
      ' Category namespaces (facts/preferences/decisions/projects) are searchable through the namespace path.',
    inputSchema: {
      type: 'object',
      properties: {
        query: {
          type: 'string',
          description: 'The keyword or phrase to search for across all memory namespaces',
        },
      },
      required: ['query'],
    },
    execute: async (rawArgs: unknown): Promise<ToolResult> => {
      const args = rawArgs as MemorySearchArgs;

      try {
        // Try hybrid search first if available
        if (hybridSearch) {
          try {
            const results = await hybridSearch.search(args.query);

            if (results.length === 0) {
              return { success: true, output: `No matches found for "${args.query}".` };
            }

            const formatted = results.map((result) => {
              const sourceLabel = result.source === 'both' ? 'keyword+vector'
                : result.source === 'vector' ? 'vector'
                  : 'keyword';
              return `[${result.namespace}:${result.line}] (${sourceLabel}, score: ${result.score.toFixed(3)}) ${result.content}\n  context: ${result.context}`;
            }).join('\n\n');

            return {
              success: true,
              output: `Found ${results.length} match${results.length === 1 ? '' : 'es'} for "${args.query}":\n\n${formatted}`,
            };
          } catch (hybridError) {
            // Fall back to keyword search on hybrid failure
            console.error('Hybrid search failed, falling back to keyword search:', hybridError);
          }
        }

        // Keyword-only fallback
        const results = store.search(args.query);

        if (results.length === 0) {
          return { success: true, output: `No matches found for "${args.query}".` };
        }

        // Format each result as a readable block with namespace, line number, and context
        const formatted = results.map((result) =>
          `[${result.namespace}:${result.line}] ${result.content}\n  context: ${result.context}`,
        ).join('\n\n');

        return {
          success: true,
          output: `Found ${results.length} match${results.length === 1 ? '' : 'es'} for "${args.query}":\n\n${formatted}`,
        };
      } catch (error) {
        return {
          success: false,
          output: '',
          error: error instanceof Error ? error.message : String(error),
        };
      }
    },
  };
}
