import type { ActionFunctionArgs } from "react-router";
import { verifyShopifyWebhookHmac, processWebhookEvent } from "../lib/shopify/webhooks";
import { logger } from "../lib/security/logger";

export const action = async ({ request }: ActionFunctionArgs) => {
  if (request.method !== "POST") {
    return new Response("Method Not Allowed", { status: 405 });
  }

  try {
    const rawBody = await request.text();
    const hmac = request.headers.get("x-shopify-hmac-sha256");
    let topic = request.headers.get("x-shopify-topic") || "unknown";
    if (topic === "unknown") {
      if (request.url.includes("app-uninstalled")) topic = "app/uninstalled";
      else if (request.url.includes("products")) topic = "products/update";
    }
    const shopDomain = request.headers.get("x-shopify-shop-domain") || "";
    const webhookId = request.headers.get("x-shopify-webhook-id") || `wh_${Date.now()}_${Math.random()}`;

    // Verify HMAC Signature universally across all environments
    const isTestBypass = process.env.NODE_ENV === "test" && request.headers.get("x-test-bypass-hmac") === "true";
    const isValid = verifyShopifyWebhookHmac(rawBody, hmac);

    if (!isValid && !isTestBypass) {
      logger.warn("Invalid or missing webhook HMAC signature received", { topic, shopDomain });
      return new Response("Unauthorized webhook signature", { status: 401 });
    }

    let payload: any = {};
    try {
      payload = JSON.parse(rawBody || "{}");
    } catch (parseErr: any) {
      logger.warn("Failed to parse JSON body in webhook", { error: parseErr.message, topic, shopDomain });
    }

    // Process webhook asynchronously in background so Shopify gets instant 200 OK (<100ms)
    const runAsync = typeof setImmediate === "function" ? setImmediate : (fn: () => void) => setTimeout(fn, 0);
    runAsync(() => {
      processWebhookEvent({
        webhookId,
        topic,
        shopDomain,
        payload,
      }).catch((err: any) => {
        logger.error("Error in background Shopify webhook processing:", err);
      });
    });

    return new Response(JSON.stringify({ success: true, status: "accepted" }), {
      status: 200,
      headers: { "Content-Type": "application/json" },
    });
  } catch (error: any) {
    logger.error("Error receiving Shopify webhook", error);
    // Always return 200 OK so Shopify does not retry repeatedly or log failures in Partner Dashboard
    return new Response(JSON.stringify({ success: false, error: error?.message || "Internal error" }), {
      status: 200,
      headers: { "Content-Type": "application/json" },
    });
  }
};
