// packages/functions/src/vercel/api/billing/webhook-handler.ts

/**
 * @fileoverview Stripe webhook handler API
 * @description Vercel API route for handling Stripe webhook events
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */

import { logger } from 'firebase-functions/v2';

import type { StripeBackConfig } from '@donotdev/core/server';

import { updateUserSubscription } from '../../../shared/billing/helpers/updateUserSubscription.js';
import { processWebhook } from '../../../shared/billing/webhookHandler.js';
import { stripe } from '../../../shared/utils.js';

import type { NextApiRequest, NextApiResponse } from 'next';

/**
 * Create Vercel webhook handler from billing config
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
export function createStripeWebhook(billingConfig: StripeBackConfig) {
  return async (req: NextApiRequest, res: NextApiResponse) => {
    if (req.method !== 'POST') {
      res.status(405).json({ error: 'Method not allowed' });
      return;
    }

    try {
      const sig = req.headers['stripe-signature'];
      if (!sig || Array.isArray(sig)) {
        throw new Error('No Stripe signature found');
      }

      const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET;
      if (!webhookSecret) {
        throw new Error('STRIPE_WEBHOOK_SECRET not configured');
      }

      // Get raw body
      const rawBody = await getRawBody(req);

      // Call shared algorithm
      await processWebhook(
        rawBody,
        sig,
        webhookSecret,
        stripe,
        billingConfig,
        updateUserSubscription,
        null // No authProvider needed for Vercel implementation
      );

      res.status(200).json({ received: true });
    } catch (error) {
      logger.error('Vercel webhook error', {
        error: error instanceof Error ? error.message : String(error),
      });
      res.status(400).json({
        error: error instanceof Error ? error.message : 'Webhook failed',
      });
    }
  };
}

async function getRawBody(req: NextApiRequest): Promise<Buffer> {
  const chunks: Buffer[] = [];
  for await (const chunk of req) {
    chunks.push(
      typeof chunk === 'string' ? Buffer.from(chunk) : (chunk as Buffer)
    );
  }
  return Buffer.concat(chunks as readonly Uint8Array[]);
}

/**
 * Next.js API route configuration
 *
 * @version 0.0.1
 * @since 0.0.1
 * @author AMBROISE PARK Consulting
 */
export const config = {
  api: { bodyParser: false },
};
