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 in constant time.
 * FAILS CLOSED: Never bypasses validation when secret is missing.
 */
export function verifyShopifyWebhookHmac(rawBody: string, hmacHeader: string | null): boolean {
  if (!hmacHeader) return false;
  const secret = process.env.SHOPIFY_API_SECRET || "";
  if (!secret) {
    logger.error("SHOPIFY_API_SECRET is not configured in environment");
    return false;
  }

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

    const calcBuf = Buffer.from(calculatedHmac, "utf8");
    const headerBuf = Buffer.from(hmacHeader, "utf8");

    if (calcBuf.length !== headerBuf.length) {
      return false;
    }

    return crypto.timingSafeEqual(calcBuf, headerBuf);
  } 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 }> {
  try {
    // Check if webhook has already been processed (Idempotency check)
    let existing = null;
    try {
      existing = await prisma.webhookEvent.findUnique({
        where: { webhookId },
      });
    } catch (dbErr: any) {
      logger.warn(`Idempotency check query warning: ${dbErr.message}`, { webhookId });
    }

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

    let shop = null;
    try {
      if (shopDomain) {
        shop = await prisma.shop.findUnique({
          where: { shopifyDomain: shopDomain },
        });
      }
    } catch (dbErr: any) {
      logger.warn(`Failed to find shop for domain ${shopDomain}: ${dbErr.message}`);
    }

    // Record Webhook Event
    let event: any = null;
    try {
      event = await prisma.webhookEvent.create({
        data: {
          webhookId,
          topic,
          shopId: shop?.id || null,
          payload: payload && typeof payload === "object" ? payload : {},
          processed: false,
        },
      });
    } catch (dbErr: any) {
      logger.warn(`Could not persist WebhookEvent record: ${dbErr.message}`, { webhookId });
    }

    // Handle specific webhook topics
    try {
      if (topic === "app/uninstalled") {
        if (shop) {
          await prisma.shop.update({
            where: { id: shop.id },
            data: {
              uninstalledAt: new Date(),
              accessToken: "shpss_sample_token",
              refreshToken: null,
              tokenExpiresAt: null,
              activePlan: "FREE",
              planHandle: "free",
              subscriptionStatus: "CANCELLED",
              cancelAtEndOfCycle: false,
              trialEndsAt: null,
              currentBillingCycleStart: null,
              currentBillingCycleEnd: null,
              lastSubscriptionSync: new Date(),
            },
          });
          await prisma.subscription.updateMany({
            where: { shopId: shop.id },
            data: {
              status: "CANCELLED",
              endedAt: new Date(),
            },
          });
          logger.info(`Merchant app uninstalled: ${shopDomain}, subscription reset to FREE`, { shopId: shop.id, shopDomain });
        } else if (shopDomain) {
          await prisma.shop.updateMany({
            where: { shopifyDomain: shopDomain },
            data: {
              uninstalledAt: new Date(),
              accessToken: "shpss_sample_token",
              refreshToken: null,
              tokenExpiresAt: null,
              activePlan: "FREE",
              planHandle: "free",
              subscriptionStatus: "CANCELLED",
              cancelAtEndOfCycle: false,
              trialEndsAt: null,
              currentBillingCycleStart: null,
              currentBillingCycleEnd: null,
              lastSubscriptionSync: new Date(),
            },
          });
          logger.info(`Merchant app uninstalled (by domain): ${shopDomain}`);
        }
      } else if (topic === "app_subscriptions/update" || topic === "app_subscriptions_update") {
        const appSubscription = payload?.app_subscription;
        const subStatus = (appSubscription?.status || "").toUpperCase();
        logger.info(`Shopify app_subscriptions/update received for ${shopDomain}: status=${subStatus}`, { payload });

        if (subStatus === "ACTIVE" && shopDomain) {
          const { BillingService } = await import("../../services/billing.server");
          await BillingService.syncSubscription(shopDomain);
        } else if (["CANCELLED", "EXPIRED", "DECLINED", "FROZEN"].includes(subStatus)) {
          if (shop) {
            await prisma.shop.update({
              where: { id: shop.id },
              data: {
                activePlan: "FREE",
                planHandle: "free",
                subscriptionStatus: "CANCELLED",
                cancelAtEndOfCycle: false,
                trialEndsAt: null,
                currentBillingCycleEnd: null,
                lastSubscriptionSync: new Date(),
              },
            });
            await prisma.subscription.updateMany({
              where: { shopId: shop.id, status: "ACTIVE" },
              data: {
                status: "CANCELLED",
                endedAt: new Date(),
              },
            });
            logger.info(`Shopify app subscription cancelled for ${shopDomain}, reverted to FREE tier`);
          }
        }
      } 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
    if (event?.id) {
      try {
        await prisma.webhookEvent.update({
          where: { id: event.id },
          data: { processed: true },
        });
      } catch (dbErr: any) {
        logger.warn(`Could not mark WebhookEvent as processed: ${dbErr.message}`, { eventId: event.id });
      }
    }

    return { processed: true, duplicate: false };
  } catch (err: any) {
    logger.error(`Fatal unhandled error processing webhook ${topic}: ${err.message}`, err);
    return { processed: false, duplicate: false };
  }
}
