/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable camelcase */
/* eslint-disable no-await-in-loop */
/* eslint-disable no-console */

import { Request, Response } from 'express';
import crypto from 'crypto';

import config from '@/shared/config/config';
import connectToDatabase from '@/shared/config/dbConfig';
import { decrypt } from './crypto';
import {
  extractLeadData,
  fetchLeadDetails,
  findActiveCaptureLead,
  findIntegrationByPageId,
  importLeads,
} from './meta.helper';

export function verifyMetaSignature(req: Request): boolean {
  try {
    const signature = req.get('x-hub-signature-256') || '';
    if (!signature.startsWith('sha256=')) return false;
    const sigHash = signature.slice(7);

    // rawBody must be set by a middleware capturing raw request body
    const rawBody = (req as any).rawBody;
    if (!rawBody) {
      console.error(
        'Raw body missing. Ensure middleware to capture raw request body is present.',
      );
      return false;
    }

    const hmac = crypto.createHmac('sha256', String(config.metaLeadSecretId));
    hmac.update(rawBody, 'utf8');

    const digest = hmac.digest('hex');

    // Use timingSafeEqual to prevent timing attacks
    const sigBuffer = Buffer.from(sigHash, 'hex');
    const digestBuffer = Buffer.from(digest, 'hex');

    if (sigBuffer.length !== digestBuffer.length) return false;

    return crypto.timingSafeEqual(digestBuffer, sigBuffer);
  } catch (err) {
    console.error('Error verifying Meta signature:', err);
    return false;
  }
}

export async function metaVerify(req: Request, res: Response) {
  const mode = req.query['hub.mode'];
  console.log('🚀 ~ metaVerify ~ mode:', mode);
  const token = req.query['hub.verify_token'];
  console.log('🚀 ~ metaVerify ~ token:', token);
  const challenge = req.query['hub.challenge'];

  console.log(
    '🚀 ~ metaVerify ~ config.metaWebhookToken:',
    config.metaWebhookToken,
  );
  if (mode === 'subscribe' && token === config.metaWebhookToken)
    return res.status(200).send(challenge);
  return res.sendStatus(403);
}

export async function metaLeadsWebhook(req: Request, res: Response) {
  console.log('Meta leads webhook');
  if (!verifyMetaSignature(req)) {
    console.error('Invalid Meta signature');
    return res.sendStatus(400);
  }
  res.status(200).json({ received: true }); // Ack immediately

  (async () => {
    let entries = Array.isArray(req.body.entry) ? req.body.entry : [];

    for (const entry of entries) {
      const changes = Array.isArray(entry.changes) ? entry.changes : [];
      for (const change of changes) {
        if (change.field !== 'leadgen') return;

        try {
          const value = change.value || {};
          const leadgen_id = value.leadgen_id;
          const page_id = value.page_id || entry.id;
          if (!leadgen_id || !page_id) {
            console.warn('Missing leadgen_id or page_id', {
              leadgen_id,
              page_id,
            });
            return;
          }

          await connectToDatabase();

          const integration = await findIntegrationByPageId(page_id);
          if (!integration) {
            console.warn('No integration for page', page_id);
            return;
          }

          const decryptedToken = decrypt({
            data: integration.encryptedPageAccessToken,
            iv: integration.iv,
            tag: integration.tag,
          });

          const leadDetails = await fetchLeadDetails(
            leadgen_id,
            decryptedToken,
          );

          const fields = leadDetails?.field_data || [];
          const leadData = extractLeadData(fields);

          const companyId = String(integration.companyId);
          const captureLead = await findActiveCaptureLead(integration, page_id);
          if (!captureLead) {
            console.warn('No active captureLead found', { companyId });
            return;
          }

          await importLeads(companyId, captureLead, [leadData], false);
        } catch (err) {
          console.error('Error processing leadgen change:', err, change);
          return;
        }
      }
    }

    console.log('metaLeadsWebhook: Processing finished');
  })();

  return;
}
