/**
 * WebFetch tool — fetch a URL and extract text content.
 *
 * Converts HTML to plain text by stripping tags.
 * Returns raw text for non-HTML content.
 */

const MAX_CONTENT = 50000;
const DEFAULT_TIMEOUT = 30000;

export const definition = {
  name: 'WebFetch',
  description: 'Fetch a URL and return its text content. Strips HTML tags for web pages. Use for reading documentation, APIs, or any public URL.',
  input_schema: {
    type: 'object',
    properties: {
      url: { type: 'string', description: 'The URL to fetch (must be fully-formed, e.g. https://example.com)' },
      prompt: { type: 'string', description: 'Optional prompt describing what information to extract (used as guidance note, not for LLM processing)' },
      timeout: { type: 'number', description: 'Optional timeout in milliseconds (default 30000)' }
    },
    required: ['url']
  }
};

/**
 * Strip HTML tags and decode common entities.
 * Lightweight alternative to a full HTML parser.
 */
function htmlToText(html) {
  let text = html;

  // Remove script and style blocks
  text = text.replace(/<script[\s\S]*?<\/script>/gi, '');
  text = text.replace(/<style[\s\S]*?<\/style>/gi, '');
  text = text.replace(/<noscript[\s\S]*?<\/noscript>/gi, '');

  // Convert block elements to newlines
  text = text.replace(/<\/(p|div|h[1-6]|li|tr|br|hr)[^>]*>/gi, '\n');
  text = text.replace(/<(br|hr)\s*\/?>/gi, '\n');

  // Strip remaining tags
  text = text.replace(/<[^>]+>/g, '');

  // Decode common HTML entities
  text = text
    .replace(/&amp;/g, '&')
    .replace(/&lt;/g, '<')
    .replace(/&gt;/g, '>')
    .replace(/&quot;/g, '"')
    .replace(/&#39;/g, "'")
    .replace(/&nbsp;/g, ' ')
    .replace(/&#(\d+);/g, (_, code) => String.fromCharCode(Number(code)));

  // Clean up whitespace
  text = text.replace(/[ \t]+/g, ' ');
  text = text.replace(/\n\s*\n/g, '\n\n');
  text = text.trim();

  return text;
}

export { htmlToText as _htmlToText };

export async function execute(input, context) {
  const { url, prompt, timeout: userTimeout } = input;

  if (!url) return { content: 'Error: url is required', is_error: true };

  // Basic URL validation
  let parsed;
  try {
    parsed = new URL(url);
  } catch {
    return { content: `Error: Invalid URL: ${url}`, is_error: true };
  }

  // Only allow http/https
  if (!['http:', 'https:'].includes(parsed.protocol)) {
    return { content: `Error: Only http/https URLs are supported`, is_error: true };
  }

  const timeout = userTimeout || DEFAULT_TIMEOUT;

  try {
    const controller = new AbortController();
    const timer = setTimeout(() => controller.abort(), timeout);

    const response = await fetch(url, {
      signal: controller.signal,
      headers: {
        'User-Agent': 'Gergy-Agent/4.2 (agentic-tools)',
        'Accept': 'text/html, application/json, text/plain, */*'
      },
      redirect: 'follow'
    });

    clearTimeout(timer);

    if (!response.ok) {
      return { content: `Error: HTTP ${response.status} ${response.statusText}`, is_error: true };
    }

    const contentType = response.headers.get('content-type') || '';
    let body = await response.text();

    // Truncate before processing
    if (body.length > MAX_CONTENT * 2) {
      body = body.slice(0, MAX_CONTENT * 2);
    }

    let text;
    if (contentType.includes('text/html') || contentType.includes('application/xhtml')) {
      text = htmlToText(body);
    } else {
      text = body;
    }

    // Final truncation
    if (text.length > MAX_CONTENT) {
      text = text.slice(0, MAX_CONTENT) + '\n...[content truncated at 50000 chars]';
    }

    let result = text || '(empty response)';

    // Prepend prompt as context if provided
    if (prompt) {
      result = `[Extraction focus: ${prompt}]\n\n${result}`;
    }

    return { content: result, is_error: false };

  } catch (err) {
    if (err.name === 'AbortError') {
      return { content: `Error: Request timed out after ${timeout}ms`, is_error: true };
    }
    return { content: `Error fetching URL: ${err.message}`, is_error: true };
  }
}
