import crypto from "crypto";
import prisma from "../../db.server";
import { logger } from "../security/logger";
import { upsertSingleProductCache, deleteProductCache } from "../../services/catalog.server";

/**
 * Validates Shopify Webhook HMAC SHA256 Signature.
 */
export function verifyShopifyWebhookHmac(rawBody: string, hmacHeader: string | null): boolean {
  if (!hmacHeader) return false;
  const secret = process.env.SHOPIFY_API_SECRET || "";
  if (!secret) return true; // Dev fallback if secret not present

  try {
    const calculatedHmac = crypto
      .createHmac("sha256", secret)
      .update(rawBody, "utf8")
      .digest("base64");

    return crypto.timingSafeEqual(Buffer.from(calculatedHmac), Buffer.from(hmacHeader));
  } catch (e) {
    return false;
  }
}

/**
 * Idempotent Webhook Event Processor.
 */
export async function processWebhookEvent({
  webhookId,
  topic,
  shopDomain,
  payload,
}: {
  webhookId: string;
  topic: string;
  shopDomain: string;
  payload: any;
}): Promise<{ processed: boolean; duplicate: boolean }> {
  // Check if webhook has already been processed (Idempotency check)
  const existing = await prisma.webhookEvent.findUnique({
    where: { webhookId },
  });

  if (existing) {
    logger.info(`Duplicate webhook received: ${webhookId} (${topic})`, { webhookId, topic, shopDomain });
    return { processed: existing.processed, duplicate: true };
  }

  const shop = await prisma.shop.findUnique({
    where: { shopifyDomain: shopDomain },
  });

  // Record Webhook Event
  const event = await prisma.webhookEvent.create({
    data: {
      webhookId,
      topic,
      shopId: shop?.id || null,
      payload,
      processed: false,
    },
  });

  // Handle specific webhook topics
  try {
    if (topic === "app/uninstalled") {
      if (shop) {
        await prisma.shop.update({
          where: { id: shop.id },
          data: { uninstalledAt: new Date() },
        });
        logger.info(`Merchant app uninstalled: ${shopDomain}`, { shopId: shop.id, shopDomain });
      }
    } else if (topic === "products/create" || topic === "products/update") {
      if (shopDomain && payload) {
        await upsertSingleProductCache(shopDomain, payload);
        logger.info(`Real-time ProductCache updated for ${shopDomain} (Product ID: ${payload.id})`, { topic, shopDomain });
      }
    } else if (topic === "products/delete") {
      if (shopDomain && payload?.id) {
        await deleteProductCache(shopDomain, String(payload.id));
        logger.info(`Real-time ProductCache item deleted for ${shopDomain} (Product ID: ${payload.id})`, { topic, shopDomain });
      }
    } else if (topic === "customers/redact") {
      if (shop && payload?.customer?.id) {
        await prisma.customer.deleteMany({
          where: { shopId: shop.id, shopifyCustomerId: String(payload.customer.id) },
        });
        logger.info(`GDPR customer data redacted for ${shopDomain}`, { customerId: payload.customer.id });
      }
    }
  } catch (err: any) {
    logger.error(`Error executing webhook handler for ${topic}: ${err.message}`, err);
  }

  // Mark event as processed
  await prisma.webhookEvent.update({
    where: { id: event.id },
    data: { processed: true },
  });

  return { processed: true, duplicate: false };
}

