#!/usr/bin/env node
/**
 * Tavily Search CLI
 *
 * - Reads TAVILY_API_KEY from env only.
 * - Prints full JSON response to stdout.
 * - Prints a simple list of URLs to stderr by default (can be disabled).
 */

const TAVILY_ENDPOINT = 'https://api.tavily.com/search';

function usage(msg) {
  if (msg) console.error(`Error: ${msg}\n`);
  console.error(`Usage:
  tavily_search.js --query "..." [--max_results 5] [--include_domains a.com,b.com] [--exclude_domains x.com,y.com]

Options:
  --query, -q              Search query (required)
  --max_results, -n        Max results (default: 5; clamped to 0..20)
  --include_domains        Comma-separated domains to include
  --exclude_domains        Comma-separated domains to exclude
  --urls-stderr            Print URL list to stderr (default: true)
  --no-urls-stderr         Disable URL list to stderr
  --urls-only              Print URLs (one per line) to stdout instead of JSON
  --help, -h               Show help

Env:
  TAVILY_API_KEY            (required) Tavily API key

Exit codes:
  0 success
  2 usage / missing required inputs
  3 network / HTTP error
  4 invalid JSON response
`);
}

function parseArgs(argv) {
  const out = {
    query: null,
    max_results: 5,
    include_domains: null,
    exclude_domains: null,
    urls_stderr: true,
    urls_only: false,
    help: false,
  };

  for (let i = 0; i < argv.length; i++) {
    const a = argv[i];
    if (a === '--help' || a === '-h') out.help = true;
    else if (a === '--query' || a === '-q') out.query = argv[++i];
    else if (a === '--max_results' || a === '-n') out.max_results = Number(argv[++i]);
    else if (a === '--include_domains') out.include_domains = argv[++i];
    else if (a === '--exclude_domains') out.exclude_domains = argv[++i];
    else if (a === '--urls-stderr') out.urls_stderr = true;
    else if (a === '--no-urls-stderr') out.urls_stderr = false;
    else if (a === '--urls-only') out.urls_only = true;
    else return { error: `Unknown arg: ${a}` };
  }

  if (Number.isNaN(out.max_results) || !Number.isFinite(out.max_results)) {
    return { error: `--max_results must be a number` };
  }
  // Tavily allows 0..20; clamp to stay in range.
  out.max_results = Math.max(0, Math.min(20, Math.trunc(out.max_results)));

  const csvToArray = (s) => {
    if (!s) return null;
    const arr = s.split(',').map(x => x.trim()).filter(Boolean);
    return arr.length ? arr : null;
  };

  out.include_domains = csvToArray(out.include_domains);
  out.exclude_domains = csvToArray(out.exclude_domains);

  return out;
}

async function main() {
  const args = parseArgs(process.argv.slice(2));
  if (args.error) {
    usage(args.error);
    process.exit(2);
  }
  if (args.help) {
    usage();
    process.exit(0);
  }

  const apiKey = process.env.TAVILY_API_KEY;
  if (!apiKey) {
    usage('TAVILY_API_KEY env var is required');
    process.exit(2);
  }

  if (!args.query) {
    usage('--query is required');
    process.exit(2);
  }

  const payload = {
    query: args.query,
    max_results: args.max_results,
  };
  if (args.include_domains) payload.include_domains = args.include_domains;
  if (args.exclude_domains) payload.exclude_domains = args.exclude_domains;

  let res;
  try {
    res = await fetch(TAVILY_ENDPOINT, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${apiKey}`,
      },
      body: JSON.stringify(payload),
    });
  } catch (e) {
    console.error(`Network error calling Tavily: ${e?.message || String(e)}`);
    process.exit(3);
  }

  if (!res.ok) {
    let bodyText = '';
    try { bodyText = await res.text(); } catch {}
    console.error(`Tavily HTTP error: ${res.status} ${res.statusText}`);
    if (bodyText) console.error(bodyText);
    process.exit(3);
  }

  let data;
  try {
    data = await res.json();
  } catch (e) {
    console.error(`Invalid JSON response from Tavily: ${e?.message || String(e)}`);
    process.exit(4);
  }

  const urls = Array.isArray(data?.results)
    ? data.results.map(r => r?.url).filter(Boolean)
    : [];

  if (args.urls_only) {
    for (const u of urls) process.stdout.write(`${u}\n`);
    process.exit(0);
  }

  process.stdout.write(JSON.stringify(data, null, 2));
  process.stdout.write('\n');

  if (args.urls_stderr && urls.length) {
    console.error('\nURLs:');
    for (const u of urls) console.error(u);
  }
}

main().catch((e) => {
  console.error(`Unexpected error: ${e?.stack || e?.message || String(e)}`);
  process.exit(1);
});
