const http = require("http");
const https = require("https");
const crypto = require("crypto");
const { loadWebhookSubs } = require("./store");

// Generate HMAC-SHA256 signature for webhook payloads
function webhookSignature(secret, payload) {
  return 'sha256=' + crypto.createHmac('sha256', secret).update(payload).digest('hex');
}

// Deliver webhook with exponential backoff (max 5 retries)
async function deliverWebhook(sub, payload, attempt) {
  attempt = attempt || 1;
  const payloadStr = JSON.stringify(payload);
  const sig = webhookSignature(sub.secret, payloadStr);
  return new Promise((resolve) => {
    try {
      const parsed = new URL(sub.endpoint_url);
      const lib = parsed.protocol === 'https:' ? https : http;
      const options = {
        hostname: parsed.hostname,
        port: parsed.port || (parsed.protocol === 'https:' ? 443 : 80),
        path: parsed.pathname + parsed.search,
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Content-Length': Buffer.byteLength(payloadStr),
          'X-PeerCortex-Signature': sig,
          'X-PeerCortex-Event': 'hijack_detected',
          'User-Agent': 'PeerCortex-Webhook/1.0'
        },
        timeout: 10000
      };
      const req = lib.request(options, (res) => {
        let body = '';
        res.on('data', c => body += c);
        res.on('end', () => {
          if (res.statusCode >= 200 && res.statusCode < 300) {
            resolve({ ok: true, status: res.statusCode });
          } else if (attempt < 5) {
            const delay = Math.pow(2, attempt) * 1000;
            setTimeout(() => deliverWebhook(sub, payload, attempt + 1).then(resolve), delay);
          } else {
            resolve({ ok: false, status: res.statusCode, error: 'max_retries' });
          }
        });
      });
      req.on('error', () => {
        if (attempt < 5) {
          const delay = Math.pow(2, attempt) * 1000;
          setTimeout(() => deliverWebhook(sub, payload, attempt + 1).then(resolve), delay);
        } else {
          resolve({ ok: false, error: 'connection_failed' });
        }
      });
      req.on('timeout', () => { req.destroy(); });
      req.write(payloadStr);
      req.end();
    } catch(e) {
      resolve({ ok: false, error: e.message });
    }
  });
}

// Fire webhooks for all subscribers of an ASN when hijack detected
async function notifyWebhooks(asn, alert) {
  const subs = loadWebhookSubs().filter(s => String(s.asn) === String(asn) && s.active !== false);
  for (const sub of subs) {
    const payload = {
      event: 'hijack_detected',
      asn: asn,
      alert: alert,
      timestamp: new Date().toISOString(),
      source: 'PeerCortex BGP Monitor'
    };
    deliverWebhook(sub, payload, 1).then(result => {
      if (!result.ok) console.warn(`[WEBHOOK] Delivery failed for AS${asn} → ${sub.endpoint_url}: ${result.error || result.status}`);
    });
  }
}

module.exports = { webhookSignature, deliverWebhook, notifyWebhooks };
