const express = require("express");
const StripeWebhookService = require("../services/stripeWebhookService");
const DisputeService = require("../services/disputeService");
const logger = require("../utils/logger");

const router = express.Router();

const WEBHOOK_SECRET = process.env.STRIPE_WEBHOOK_SECRET;

/**
 * POST /stripe/webhooks
 * Stripe webhook endpoint - receives events from Stripe.
 * Must use raw body for signature verification.
 */
router.post("/", async (req, res) => {
  const signature = req.headers["stripe-signature"];

  if (!signature) {
    logger.warn("Webhook request missing stripe-signature header");
    return res.status(400).json({ error: "Missing signature" });
  }

  if (!WEBHOOK_SECRET) {
    logger.error("STRIPE_WEBHOOK_SECRET not configured");
    return res.status(500).json({ error: "Webhook not configured" });
  }

  let event;

  try {
    // Use rawBody stored by bodyParser in server.js
    event = StripeWebhookService.constructEvent(
      req.rawBody,
      signature,
      WEBHOOK_SECRET
    );
  } catch (err) {
    logger.error("Webhook signature verification failed", {
      error: err.message,
    });
    return res.status(400).json({ error: "Invalid signature" });
  }

  // Log event receipt for debugging
  // For Connect account events, event.account contains the connected account ID
  logger.info("Stripe webhook received", {
    eventId: event.id,
    eventType: event.type,
    connectedAccount: event.account || null,
  });

  try {
    switch (event.type) {
      case "account.updated":
        await StripeWebhookService.handleAccountUpdated(event.data.object);
        break;

      case "payout.paid":
        // Payout to connected account's bank succeeded
        await StripeWebhookService.handlePayoutPaid(
          event.data.object,
          event.account
        );
        break;

      case "payout.failed":
        // Payout to connected account's bank failed
        await StripeWebhookService.handlePayoutFailed(
          event.data.object,
          event.account
        );
        break;

      case "payout.canceled":
        // Payout was canceled before being deposited
        await StripeWebhookService.handlePayoutCanceled(
          event.data.object,
          event.account
        );
        break;

      case "account.application.deauthorized":
        // Owner disconnected their Stripe account from our platform
        await StripeWebhookService.handleAccountDeauthorized(event.account);
        break;

      case "charge.dispute.created":
        // Renter disputed a charge with their bank
        await DisputeService.handleDisputeCreated(event.data.object);
        break;

      case "charge.dispute.closed":
      case "charge.dispute.funds_reinstated":
      case "charge.dispute.funds_withdrawn":
        // Dispute was resolved (won, lost, or warning closed)
        await DisputeService.handleDisputeClosed(event.data.object);
        break;

      default:
        logger.info("Unhandled webhook event type", { type: event.type });
    }

    // Always return 200 to acknowledge receipt
    res.json({ received: true, eventId: event.id });
  } catch (error) {
    logger.error("Error processing webhook", {
      eventId: event.id,
      eventType: event.type,
      error: error.message,
      stack: error.stack,
    });

    // Still return 200 to prevent Stripe retries for processing errors
    // Failed payouts will be handled by retry job
    res.json({ received: true, eventId: event.id, error: error.message });
  }
});

module.exports = router;
