import express from 'express';
import { webhookDb } from '../database/db.js';

const router = express.Router();

// GET /api/webhooks — list all webhooks for the user
router.get('/', async (req, res) => {
  try {
    const webhooks = await webhookDb.getAll(req.user.id);
    res.json({ webhooks });
  } catch (error) {
    res.status(500).json({ error: 'Failed to fetch webhooks' });
  }
});

// POST /api/webhooks — create a webhook
router.post('/', async (req, res) => {
  try {
    const { name, url, method, headers, description } = req.body;
    if (!name || !name.trim()) return res.status(400).json({ error: 'Name is required' });
    if (!url || !url.trim()) return res.status(400).json({ error: 'URL is required' });

    try { new URL(url); } catch { return res.status(400).json({ error: 'Invalid URL' }); }

    const allowedMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
    const m = (method || 'POST').toUpperCase();
    if (!allowedMethods.includes(m)) return res.status(400).json({ error: 'Invalid HTTP method' });

    // Validate headers is valid JSON if provided
    let headersStr = '{}';
    if (headers) {
      if (typeof headers === 'string') {
        try { JSON.parse(headers); headersStr = headers; } catch { return res.status(400).json({ error: 'Headers must be valid JSON' }); }
      } else {
        headersStr = JSON.stringify(headers);
      }
    }

    const webhook = await webhookDb.create(req.user.id, {
      name: name.trim(),
      url: url.trim(),
      method: m,
      headers: headersStr,
      description: description?.trim() || null
    });
    res.json({ success: true, webhook });
  } catch (error) {
    res.status(500).json({ error: 'Failed to create webhook' });
  }
});

// PUT /api/webhooks/:id — update a webhook
router.put('/:id', async (req, res) => {
  try {
    const { name, url, method, headers, description } = req.body;
    if (!name || !name.trim()) return res.status(400).json({ error: 'Name is required' });
    if (!url || !url.trim()) return res.status(400).json({ error: 'URL is required' });

    try { new URL(url); } catch { return res.status(400).json({ error: 'Invalid URL' }); }

    let headersStr = '{}';
    if (headers) {
      if (typeof headers === 'string') {
        try { JSON.parse(headers); headersStr = headers; } catch { return res.status(400).json({ error: 'Headers must be valid JSON' }); }
      } else {
        headersStr = JSON.stringify(headers);
      }
    }

    const updated = await webhookDb.update(Number(req.params.id), req.user.id, {
      name: name.trim(),
      url: url.trim(),
      method: (method || 'POST').toUpperCase(),
      headers: headersStr,
      description: description?.trim() || null
    });

    if (!updated) return res.status(404).json({ error: 'Webhook not found' });
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: 'Failed to update webhook' });
  }
});

// DELETE /api/webhooks/:id — delete a webhook
router.delete('/:id', async (req, res) => {
  try {
    const deleted = await webhookDb.delete(Number(req.params.id), req.user.id);
    if (!deleted) return res.status(404).json({ error: 'Webhook not found' });
    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: 'Failed to delete webhook' });
  }
});

// POST /api/webhooks/:id/test — fire a test request to the webhook
router.post('/:id/test', async (req, res) => {
  try {
    const webhook = await webhookDb.getById(Number(req.params.id), req.user.id);
    if (!webhook) return res.status(404).json({ error: 'Webhook not found' });

    let parsedHeaders = {};
    try { parsedHeaders = JSON.parse(webhook.headers || '{}'); } catch { /* ignore */ }

    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), 10000);

    try {
      const fetchOptions = {
        method: webhook.method,
        headers: {
          'Content-Type': 'application/json',
          'User-Agent': 'UpfynAI-Webhook/1.0',
          ...parsedHeaders
        },
        signal: controller.signal
      };

      // Add test body for methods that support it
      if (['POST', 'PUT', 'PATCH'].includes(webhook.method)) {
        fetchOptions.body = JSON.stringify({
          event: 'test',
          webhook_id: webhook.id,
          webhook_name: webhook.name,
          timestamp: new Date().toISOString()
        });
      }

      const response = await fetch(webhook.url, fetchOptions);
      clearTimeout(timeout);

      let body;
      const contentType = response.headers.get('content-type') || '';
      if (contentType.includes('application/json')) {
        body = await response.json();
      } else {
        body = await response.text();
        if (body.length > 2000) body = body.slice(0, 2000) + '...';
      }

      await webhookDb.updateLastTriggered(webhook.id);

      res.json({
        success: true,
        result: {
          status: response.status,
          statusText: response.statusText,
          body,
          headers: Object.fromEntries(response.headers.entries())
        }
      });
    } catch (fetchError) {
      clearTimeout(timeout);
      res.json({
        success: false,
        result: {
          error: fetchError.name === 'AbortError' ? 'Request timed out (10s)' : fetchError.message
        }
      });
    }
  } catch (error) {
    res.status(500).json({ error: 'Failed to test webhook' });
  }
});

export default router;
