/**
 * HTTP utilities - Fetch helpers and HTTP operations
 */
const http = require('http');
const { TIMEOUTS } = require('../../constants');

/**
 * Fetch with automatic timeout
 * Drop-in replacement for fetch() with AbortSignal timeout
 */
function fetchT(url, opts = {}, timeoutMs = TIMEOUTS.HTTP_DEFAULT) {
  // Caddy admin API rejects Node.js undici fetch - use raw http.request
  if (url.includes(':2019')) {
    return _httpFetch(url, opts, timeoutMs);
  }
  
  if (!opts.signal) {
    opts = { ...opts, signal: AbortSignal.timeout(timeoutMs) };
  }
  delete opts.timeout;
  return fetch(url, opts);
}

/**
 * Raw http.request wrapper for Caddy admin API
 */
function _httpFetch(url, opts = {}, timeoutMs = TIMEOUTS.HTTP_DEFAULT) {
  return new Promise((resolve, reject) => {
    const parsed = new URL(url);
    const options = {
      hostname: parsed.hostname,
      port: parsed.port || 2019,
      path: parsed.pathname + parsed.search,
      method: (opts.method || 'GET').toUpperCase(),
      headers: { ...opts.headers },
      timeout: timeoutMs,
    };
    
    if (opts.body) {
      options.headers['Content-Length'] = Buffer.byteLength(opts.body);
    }
    
    const MAX_RESPONSE_SIZE = 10 * 1024 * 1024; // 10MB
    const req = http.request(options, (res) => {
      let data = '';
      let size = 0;
      
      res.on('data', chunk => {
        size += chunk.length;
        if (size > MAX_RESPONSE_SIZE) {
          res.destroy();
          reject(new Error(`Response from ${url} exceeded ${MAX_RESPONSE_SIZE} bytes`));
          return;
        }
        data += chunk;
      });
      
      res.on('end', () => {
        resolve({
          ok: res.statusCode >= 200 && res.statusCode < 300,
          status: res.statusCode,
          statusText: res.statusMessage,
          json: () => Promise.resolve(JSON.parse(data)),
          text: () => Promise.resolve(data),
          headers: { get: (k) => res.headers[k.toLowerCase()] },
        });
      });
    });
    
    req.on('timeout', () => {
      req.destroy();
      reject(new Error(`Request to ${url} timed out after ${timeoutMs}ms`));
    });
    req.on('error', reject);
    if (opts.body) req.write(opts.body);
    req.end();
  });
}

module.exports = { fetchT };
