import { Router, Request, Response, NextFunction } from "express"
import express from "express"
import { addAsync } from "@awaitjs/express"
import { ghAppMiddleware } from "../github/github-app.js"
import { stripeWebhookHandler } from "../endpoints/stripe-webhook.js"
import { logger } from "../utils/logger.js"
import * as Sentry from "@sentry/node"
import { ROUTES } from "../constants/index.js"

// Using addAsync to properly handle async route handlers
const router = addAsync(Router()) as any

// GitHub webhook handler
// MUST be mounted before express.json() middleware
router.postAsync(ROUTES.GITHUB_WEBHOOKS, async (req: Request, res: Response, next: NextFunction) => {
  const eventType = (req.headers["x-github-event"] as string) || "unknown_event"
  const deliveryId = (req.headers["x-github-delivery"] as string) || "unknown_delivery"
  const contentLength = req.headers["content-length"]

  // Note: req.body is NOT available here — express.json() runs AFTER webhook routes
  // to preserve raw body stream for Octokit's signature verification.
  // Repo/PR context is logged by the webhook handlers in github-app.ts instead.
  const webhookLogContext = {
    requestId: req.requestId,
    traceId: req.traceId,
    operation: "github_webhook",
    eventType,
    deliveryId,
  }

  logger.info("Processing GitHub webhook", webhookLogContext, { contentLength, eventType })

  try {
    await ghAppMiddleware(req, res, next)

    if (!res.headersSent) {
      logger.warn("GitHub webhook middleware did not send response", webhookLogContext)
      res
        .status(200)
        .send(
          "Webhook acknowledged by server; no specific listener action taken or default passthrough.",
        )
    }
  } catch (error) {
    logger.error(
      "Error during GitHub webhook processing",
      webhookLogContext,
      {},
      error as Error,
    )

    Sentry.captureException(error)
    if (!res.headersSent) {
      res
        .status(500)
        .send("Webhook received, but an unexpected server error occurred during processing.")
    }
  }
})

// Stripe webhook handler (must use raw body parser)
// Using postAsync to properly catch and forward errors to Express error middleware
router.postAsync(ROUTES.STRIPE_WEBHOOKS, express.raw({ type: "application/json" }), stripeWebhookHandler)

export default router
