import { Request, Response } from "express";
import { timingSafeEqual } from "crypto";
import { revenuecatConfig } from "../config/revenuecat";
import {
  processRevenueCatWebhookEvent,
  type RevenueCatWebhookEventPayload,
} from "../services/revenuecatWebhookService";

const TAG = "[revenuecat:webhook]";

/** Constant-time string comparison to prevent timing attacks on webhook secret. */
function safeEquals(a: string, b: string): boolean {
  if (a.length !== b.length) return false;
  return timingSafeEqual(new Uint8Array(Buffer.from(a)), new Uint8Array(Buffer.from(b)));
}

function verifyWebhookAuthorization(req: Request): boolean {
  const secret = revenuecatConfig.webhookSecret;
  if (!secret) {
    console.warn(
      `${TAG} REVENUECAT_WEBHOOK_SECRET not configured — accepting webhook without auth (dev only)`,
    );
    return true;
  }

  const authHeader = req.headers.authorization?.trim();
  if (!authHeader || typeof authHeader !== "string") {
    console.warn(
      `${TAG} Auth rejected — no Authorization header present`,
    );
    return false;
  }

  if (safeEquals(authHeader, secret)) return true;
  if (safeEquals(authHeader, `Bearer ${secret}`)) return true;

  const stripped = authHeader.replace(/^Bearer\s+/i, "");
  if (stripped !== authHeader && safeEquals(stripped, secret)) return true;

  console.warn(
    `${TAG} Auth mismatch — header length=${authHeader.length} expected=${secret.length} or ${`Bearer ${secret}`.length}`,
  );
  return false;
}

/**
 * POST /api/v1/revenuecat/webhook
 * RevenueCat server notifications — source of truth for subscription state on User.
 */
export const revenuecatWebhook = async (req: Request, res: Response) => {
  try {
    if (!verifyWebhookAuthorization(req)) {
      console.warn(`${TAG} Invalid webhook authorization`);
      return res.status(401).json({ success: false, message: "Unauthorized" });
    }

    const body = req.body as { event?: RevenueCatWebhookEventPayload };
    const event = body?.event;

    if (!event || typeof event !== "object") {
      console.warn(`${TAG} Missing event in body`);
      return res.status(400).json({ success: false, message: "Invalid payload" });
    }

    const result = await processRevenueCatWebhookEvent(event);

    if (!result.userFound) {
      return res.status(200).json({
        success: false,
        message: result.message ?? "User not found",
      });
    }

    return res.status(200).json({
      success: true,
      message: result.message ?? "OK",
      duplicate: result.duplicate ?? false,
    });
  } catch (err) {
    console.error(`${TAG} Handler error:`, err);
    return res.status(500).json({ success: false, message: "Webhook handler error" });
  }
};
