const { z } = require('zod');
const { Tool } = require('@langchain/core/tools');
const { getEnvironmentVariable } = require('@langchain/core/utils/env');

class GoogleSearchResults extends Tool {
  static lc_name() {
    return 'google';
  }

  constructor(fields = {}) {
    super(fields);
    this.name = 'google';
    this.envVarApiKey = 'GOOGLE_SEARCH_API_KEY';
    this.envVarSearchEngineId = 'GOOGLE_CSE_ID';
    this.override = fields.override ?? false;
    this.apiKey = fields[this.envVarApiKey] ?? getEnvironmentVariable(this.envVarApiKey);
    this.searchEngineId =
      fields[this.envVarSearchEngineId] ?? getEnvironmentVariable(this.envVarSearchEngineId);

    if (!this.override && (!this.apiKey || !this.searchEngineId)) {
      throw new Error(
        `Missing ${this.envVarApiKey} or ${this.envVarSearchEngineId} environment variable.`,
      );
    }

    this.kwargs = fields?.kwargs ?? {};
    this.name = 'google';
    this.description =
      'A search engine optimized for comprehensive, accurate, and trusted results. Useful for when you need to answer questions about current events.';

    this.schema = z.object({
      query: z.string().min(1).describe('The search query string.'),
      max_results: z
        .number()
        .min(1)
        .max(10)
        .optional()
        .describe('The maximum number of search results to return. Defaults to 10.'),
      // Note: Google API has its own parameters for search customization, adjust as needed.
    });
  }

  async _call(input) {
    const validationResult = this.schema.safeParse(input);
    if (!validationResult.success) {
      throw new Error(`Validation failed: ${JSON.stringify(validationResult.error.issues)}`);
    }

    const { query, max_results = 5 } = validationResult.data;

    const response = await fetch(
      `https://www.googleapis.com/customsearch/v1?key=${this.apiKey}&cx=${
        this.searchEngineId
      }&q=${encodeURIComponent(query)}&num=${max_results}`,
      {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
        },
      },
    );

    const json = await response.json();
    if (!response.ok) {
      throw new Error(`Request failed with status ${response.status}: ${json.error.message}`);
    }

    return JSON.stringify(json);
  }
}

module.exports = GoogleSearchResults;
