const crypto = require('crypto');
const db = require('../database');

/**
 * Trigger webhooks for a specific event type
 * @param {string} eventType - The event type (e.g., 'game.added')
 * @param {object} data - The payload data to send
 */
async function triggerWebhook(eventType, data) {
  try {
    // Get all enabled webhooks that are subscribed to this event
    const webhooks = db.prepare(`
      SELECT * FROM webhooks 
      WHERE enabled = 1
    `).all();

    if (webhooks.length === 0) {
      return; // No webhooks configured
    }

    // Filter webhooks that are subscribed to this event
    const subscribedWebhooks = webhooks.filter(webhook => {
      try {
        const events = JSON.parse(webhook.events);
        return events.includes(eventType);
      } catch (err) {
        console.error(`Invalid events JSON for webhook ${webhook.id}:`, err);
        return false;
      }
    });

    if (subscribedWebhooks.length === 0) {
      return; // No webhooks subscribed to this event
    }

    // Build the payload
    const payload = {
      event: eventType,
      timestamp: new Date().toISOString(),
      data: data
    };

    // Send to each webhook asynchronously (non-blocking)
    subscribedWebhooks.forEach(webhook => {
      sendWebhook(webhook, payload, eventType).catch(err => {
        console.error(`Error sending webhook ${webhook.id}:`, err);
      });
    });

  } catch (err) {
    console.error('Error triggering webhooks:', err);
  }
}

/**
 * Send a webhook to a specific URL
 * @param {object} webhook - The webhook configuration
 * @param {object} payload - The payload to send
 * @param {string} eventType - The event type
 */
async function sendWebhook(webhook, payload, eventType) {
  const payloadString = JSON.stringify(payload);
  
  // Generate HMAC signature
  const signature = 'sha256=' + crypto
    .createHmac('sha256', webhook.secret)
    .update(payloadString)
    .digest('hex');

  const startTime = Date.now();
  let responseStatus = null;
  let errorMessage = null;

  try {
    // Send the webhook
    const response = await fetch(webhook.url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Webhook-Signature': signature,
        'X-Webhook-Event': eventType,
        'User-Agent': 'Jackbox-Game-Picker-Webhook/1.0'
      },
      body: payloadString,
      // Set a timeout of 5 seconds
      signal: AbortSignal.timeout(5000)
    });

    responseStatus = response.status;

    if (!response.ok) {
      errorMessage = `HTTP ${response.status}: ${response.statusText}`;
    }

  } catch (err) {
    errorMessage = err.message;
    responseStatus = 0; // Indicates connection/network error
  }

  // Log the webhook call
  try {
    db.prepare(`
      INSERT INTO webhook_logs (webhook_id, event_type, payload, response_status, error_message)
      VALUES (?, ?, ?, ?, ?)
    `).run(webhook.id, eventType, payloadString, responseStatus, errorMessage);
  } catch (logErr) {
    console.error('Error logging webhook call:', logErr);
  }

  const duration = Date.now() - startTime;
  
  if (errorMessage) {
    console.error(`Webhook ${webhook.id} (${webhook.name}) failed: ${errorMessage} (${duration}ms)`);
  } else {
    console.log(`Webhook ${webhook.id} (${webhook.name}) sent successfully: ${responseStatus} (${duration}ms)`);
  }
}

/**
 * Verify a webhook signature
 * @param {string} signature - The signature from the X-Webhook-Signature header
 * @param {string} payload - The raw request body as a string
 * @param {string} secret - The webhook secret
 * @returns {boolean} - True if signature is valid
 */
function verifyWebhookSignature(signature, payload, secret) {
  if (!signature || !signature.startsWith('sha256=')) {
    return false;
  }

  const expectedSignature = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  // Use timing-safe comparison to prevent timing attacks
  try {
    return crypto.timingSafeEqual(
      Buffer.from(signature),
      Buffer.from(expectedSignature)
    );
  } catch (err) {
    return false;
  }
}

module.exports = {
  triggerWebhook,
  verifyWebhookSignature
};

