import { DynamicStructuredTool } from '@langchain/core/tools';
import { z } from 'zod';
import type { FastifyBaseLogger } from 'fastify';

/**
 * ArXiv Search Tool
 *
 * Searches arXiv for academic papers using the LangChain ArxivRetriever.
 * Free, no API key required.
 */

export interface ArxivSearchToolConfig {
  logger: FastifyBaseLogger;
}

export function createArxivSearchTool(config: ArxivSearchToolConfig): DynamicStructuredTool {
  const { logger } = config;

  return new DynamicStructuredTool({
    name: 'ArxivSearch',
    description: 'Search arXiv for academic papers. Returns titles, authors, abstracts, and PDF links. Use this for scientific or technical research queries instead of WebSearch.',
    schema: z.object({
      query: z.string().describe('The research query'),
      max_results: z.number().optional().default(5).describe('Maximum number of papers to return (default: 5)'),
    }),
    func: async ({ query, max_results }) => {
      logger.debug({ query, max_results }, 'Executing ArxivSearch tool');

      try {
        const { ArxivRetriever } = await import('@langchain/community/retrievers/arxiv');

        const retriever = new ArxivRetriever({
          getFullDocuments: false,
          maxSearchResults: max_results,
        });

        const docs = await retriever.invoke(query);

        const results = docs.map(doc => {
          const meta = doc.metadata as Record<string, any>;
          // Derive PDF URL from abstract URL: /abs/ID -> /pdf/ID
          const pdfUrl = typeof meta.url === 'string'
            ? meta.url.replace('/abs/', '/pdf/')
            : undefined;

          return {
            title: meta.title,
            authors: Array.isArray(meta.authors) ? meta.authors : [],
            abstract: doc.pageContent,
            published: meta.published,
            url: meta.url,
            pdf_url: pdfUrl,
          };
        });

        logger.info({ query, resultCount: results.length }, 'arXiv search completed');

        return JSON.stringify({ query, results });
      } catch (error) {
        logger.error({ error, query }, 'ArxivSearch tool failed');
        return JSON.stringify({ error: error instanceof Error ? error.message : String(error) });
      }
    },
  });
}
