console.log(`[qc] script loaded`)

const initializePosthog = () => {
  !function(t,e){var o,n,p,r;e.__SV||(window.posthog && window.posthog.__loaded)||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init rs ls wi ns us ts ss capture calculateEventProperties vs register register_once register_for_session unregister unregister_for_session gs getFeatureFlag getFeatureFlagPayload getFeatureFlagResult isFeatureEnabled reloadFeatureFlags updateFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSurveysLoaded onSessionId getSurveys getActiveMatchingSurveys renderSurvey displaySurvey cancelPendingSurvey canRenderSurvey canRenderSurveyAsync identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException startExceptionAutocapture stopExceptionAutocapture loadToolbar get_property getSessionProperty fs ds createPersonProfile setInternalOrTestUser ps Qr opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing get_explicit_consent_status is_capturing clear_opt_in_out_capturing hs debug M cs getPageViewId captureTraceFeedback captureTraceMetric Kr".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
    posthog.init('phc_jYUzT3zEYG4ZdnGs6jFi5cSnl06IM9Wx2rQ7CPtVB7R', {
        api_host: 'https://us.i.posthog.com',
        defaults: '2026-01-30',
        person_profiles: 'identified_only',
        autocapture: false,
        capture_pageview: false,
        capture_pageleave: false,
        disable_session_recording: true,
        capture_exceptions: false,
        disable_surveys: true,
        capture_heatmaps: false,
        enable_heatmaps: false,
        capture_dead_clicks: false,
        capture_performance: false,
        loaded: (posthog) => {
            posthog.register({
                app_name: 'checkout',
            })
        },
    })
}

initializePosthog();

// ============================================================================
// ERROR HANDLING & LOGGING
// ============================================================================

// Simple logger for shopify script
const logger = {
  debug: (message, data) => {
    console.debug(`[qc] ${message}`, data !== undefined ? data : '')
  },
  info: (message, data) => {
    console.log(`[qc] ${message}`, data !== undefined ? data : '')
  },
  warn: (message, data) => {
    console.warn(`[qc] ${message}`, data !== undefined ? data : '')
  },
  error: (message, error, data) => {
    console.error(`[qc] ${message}`, error || '', data !== undefined ? data : '')
    
    // Capture to PostHog in production
    if (typeof posthog !== 'undefined' && posthog.capture) {
      try {
        const errorObj = error instanceof Error ? error : new Error(String(error || message))
        posthog.capture('$exception', {
          $exception_type: errorObj.name,
          $exception_message: errorObj.message,
          $exception_stack_trace_raw: errorObj.stack,
          source: 'shopify_script',
          app_name: 'checkout',
          additional_context: data,
          script_url: window.location.href,
        })
      } catch (captureError) {
        console.error('[qc] Failed to capture error to PostHog:', captureError)
      }
    }
  }
}

// Global error handler
const initGlobalErrorHandler = () => {
  const originalOnError = window.onerror
  const originalOnUnhandledRejection = window.onunhandledrejection

  // Handle uncaught exceptions
  window.onerror = (message, filename, lineno, colno, error) => {
    logger.error(
      'Uncaught exception',
      error || new Error(String(message)),
      { filename, lineno, colno, type: 'unhandled_exception' }
    )

    if (typeof originalOnError === 'function') {
      return originalOnError(message, filename, lineno, colno, error)
    }
    return false
  }

  // Handle unhandled promise rejections
  window.onunhandledrejection = (event) => {
    const error = event.reason instanceof Error 
      ? event.reason 
      : new Error(String(event.reason))
    
    logger.error(
      'Unhandled promise rejection',
      error,
      { type: 'unhandled_rejection' }
    )

    if (typeof originalOnUnhandledRejection === 'function') {
      originalOnUnhandledRejection(event)
    }
  }
}

// Initialize error handler
initGlobalErrorHandler()

// ============================================================================
// GLOBAL STATE
// ============================================================================

// Global variables to store cart and Navidium states
window.qcLastCartState = null
window.qcNavidiumResponse = null
window.qcNavidiumCleanupInProgress = false

{
  const userAgent = navigator.userAgent

  // polyfill event.path for Safari and Firefox
  if (!('path' in Event.prototype)) {
    Object.defineProperty(Event.prototype, 'path', {
      get: function () {
        var path = []
        var currentElem = this.target
        while (currentElem) {
          path.push(currentElem)
          currentElem = currentElem.parentElement
        }
        if (path.indexOf(window) === -1 && path.indexOf(document) === -1)
          path.push(document)
        if (path.indexOf(window) === -1) path.push(window)
        return path
      },
    })
  }

  // used to send logs in case of default chackout opening
  // CreateCheckoutMonitoringCaseRequestBody
  // requestBodyType = { storeId: string, reason: string, isExpected?: boolean, details?: string }

  async function sendMonitoringPostRequest(requestBody) {
    // this constructor is needed solely for PR environments
    // prod env should always have the same url
    // 'https://api.qcpg.cc/api/v2/checkouts/monitoring'

    const checkoutUrl = `https://checkout.qcpg.cc`
    const regex = /https:\/\/checkout\.(.*?)\.qcpg\.cc/
    const match = checkoutUrl.match(regex)
    let apiEnv = ''

    if (match && match[1]) {
      apiEnv = match[1] + '.'
    }

    const url = 'https://api.' + apiEnv + 'qcpg.cc/api/v2/checkouts/monitoring'

    return fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(requestBody),
    })
      .then((response) => {
        if (!response.ok) {
          throw new Error(`HTTP error! Status: ${response.status}`)
        }
        return response.json()
      })
      .catch((error) => {
        logger.error('Monitoring request error', error, { userAgent })
        sendMonitoringPostRequest({
          storeId: `5b8cd47a-21de-4c80-b862-5bace93b79ee`,
          reason: `[script]: sendMonitoringPostRequest failed with error: ${error.message}`,
          details: JSON.stringify({ userAgent }),
        })
      })
  }

  // helper functions
  /**
   * qcShowDefaultCheckout is used to show default checkout.
   * @param element any
   */
  window.qcShowDefaultCheckout = (element, redirectLink) => {
    console.log(
      '[qc] 🔍 FALLBACK: qcShowDefaultCheckout called, QC_SHOW_DEFAULT before:',
      window.QC_SHOW_DEFAULT,
    )

    // If we have a redirect link, use it directly (more reliable)
    if (redirectLink) {
      console.log('[qc] 🚀 Using direct redirect to:', redirectLink)
      window.location.href = redirectLink
      window.QC_SHOW_DEFAULT = true
      return
    }

    // Fallback to simulating button click if no redirect link
    console.log('[qc] 🔄 No redirect link, simulating button click')
    window.QC_SHOW_DEFAULT = true
    console.log('[qc] 🔍 FALLBACK: Set QC_SHOW_DEFAULT to true, clicking button')

    // call click event again with default behavior
    element.classList.remove('disabled')
    element.removeAttribute('disabled')
    element.click()
  }
  // list of domains where untrusted clicks are allowed
  const domainsWithUntrustedClicksDisallowed = ['buttonsbebe.com']

  // if true, will prevent isTrusted check execution
  const areNotTrustedClicksDisallowed = domainsWithUntrustedClicksDisallowed.some(
    (domain) => {
      if (window.location.href.split('?')[0].includes(domain)) {
        return true
      }

      return false
    },
  )

  const removeHashFromUrl = (url) => {
    const urlObj = new URL(url)
    urlObj.hash = ''
    return urlObj.toString()
  }

  // properly incode signs to avoid parsing issues
  const replaceBreakingCharacters = (inputString) => {
    return inputString
      .replace(/%(?!25)/g, '%25')
      .replace(/#/g, '%23')
      .replace(/&/g, '%26')
      .replace(/\+/g, '%2B')
  }

  // products might have properties with special characters, so we need to encode them
  const encode = (inputObject) => {
    const replacedObject = {}

    for (const key in inputObject) {
      if (inputObject.hasOwnProperty(key)) {
        let modifiedKey = replaceBreakingCharacters(key)

        let value = inputObject[key]

        if (typeof value === 'string') {
          let modifiedValue = replaceBreakingCharacters(value)

          replacedObject[modifiedKey] = modifiedValue
        } else {
          replacedObject[modifiedKey] = value
        }
      }
    }

    return replacedObject
  }

  const formatProducts = (products) => {
    const formatted = products.map((product) => {
      return product.properties
        ? { ...product, properties: encode(product.properties) }
        : product
    })

    return formatted
  }

  // https://discountoncartpro.com/
  // START
  const discount = {
    code: '',
    type: '',
  }

  const setDiscount = ({ title, type }) => {
    discount.code = title
    discount.type = type
  }

  const resetDiscount = () => {
    window.discountOnCartProApp.removeCode(discount.code)
    setDiscount({ title: '', type: '' })
  }
  // END

  // Navidium app detection - check multiple possible indicators
  const hasNavidiumApp = () => {
    const navidiumButton = document.getElementById('nvd-with-checkout-btn')
    const navidiumSubtotal = document.getElementById('nvd-subtotal')
    const navidiumMini = document.querySelector('.nvd-mini')
    const navidiumWidget = document.querySelector('[class*="navidium"]')
    const navidiumScript = document.querySelector('script[src*="navidium"]')

    console.log('[qc] Checking for Navidium app presence...')
    console.log('[qc] - nvd-with-checkout-btn:', !!navidiumButton)
    console.log('[qc] - nvd-subtotal:', !!navidiumSubtotal)
    console.log('[qc] - .nvd-mini:', !!navidiumMini)
    console.log('[qc] - [class*="navidium"]:', !!navidiumWidget)
    console.log('[qc] - script[src*="navidium"]:', !!navidiumScript)

    if (
      navidiumButton ||
      navidiumSubtotal ||
      navidiumMini ||
      navidiumWidget ||
      navidiumScript
    ) {
      console.log('[qc] ✅ Navidium app DETECTED on store')
      return true
    }

    console.log('[qc] ❌ Navidium app NOT detected on store')
    return false
  }

  // Function to send cart data to QuickCheckout backend for Navidium processing
  async function sendCartToNavidiumBackend(cartData) {
    if (!hasNavidiumApp()) {
      console.log('[qc] Navidium not detected, skipping backend call')
      return null
    }

    const checkoutUrl = `https://checkout.qcpg.cc`
    const regex = /https:\/\/checkout\.(.*?)\.qcpg\.cc/
    const match = checkoutUrl.match(regex)
    let apiEnv = ''

    if (match && match[1]) {
      apiEnv = match[1] + '.'
    }

    const url = 'https://api.' + apiEnv + 'qcpg.cc/api/v2/checkouts/navidium-protection'

    // Filter out items that already have Navidium protection
    const itemsWithoutProtection = cartData.items.filter((item) => {
      const hasProtection =
        item.properties && item.properties._navidium_protection === 'true'
      if (hasProtection) {
        console.log(
          '[qc] 🛡️ Excluding existing protection item from Navidium API request:',
          {
            title: item.title,
            variant_id: item.variant_id,
            price: item.price / 100,
          },
        )
      }
      return !hasProtection
    })

    console.log('[qc] 📊 Cart filtering results:', {
      original_items: cartData.items.length,
      items_without_protection: itemsWithoutProtection.length,
      protection_items_excluded: cartData.items.length - itemsWithoutProtection.length,
    })

    // Format cart items for Navidium API (excluding protection items)
    const navidiumItems = itemsWithoutProtection.map((item) => ({
      product_id: item.variant_id ? item.variant_id.toString() : item.id.toString(),
      price: item.final_line_price / item.quantity / 100, // Use actual price per item after ALL discounts
      quantity: item.quantity,
      product_type: item.product_type || '',
      sku: item.sku || '',
    }))

    // Calculate total price in dollars (excluding protection items)
    const totalPriceWithoutProtection =
      itemsWithoutProtection.reduce((sum, item) => {
        return sum + item.final_line_price // Use final_line_price which includes ALL discounts
      }, 0) / 100

    // Default to United States if country not available
    const countryName = 'United States'

    try {
      console.log('[qc] 📡 STEP 1: Sending cart data to our backend')
      console.log('[qc] Endpoint:', url)
      console.log(
        '[qc] 💰 PRICE TRACE - Original cart total_price (cents):',
        cartData.total_price,
      )
      console.log(
        '[qc] 💰 PRICE TRACE - Original total_price (dollars):',
        cartData.total_price / 100,
      )
      console.log(
        '[qc] 💰 PRICE TRACE - Filtered total_price (dollars):',
        totalPriceWithoutProtection,
      )
      console.log(
        '[qc] 📦 PRICE TRACE - Original items from cart:',
        cartData.items.map((item) => ({
          title: item.title,
          variant_id: item.variant_id,
          price_cents: item.price,
          price_dollars: item.price / 100,
          line_price_cents: item.line_price,
          line_price_dollars: item.line_price / 100,
          final_line_price_cents: item.final_line_price,
          final_line_price_dollars: item.final_line_price / 100,
          quantity: item.quantity,
        })),
      )
      console.log('[qc] 📦 PRICE TRACE - Formatted items for Navidium:', navidiumItems)
      console.log('[qc] Request payload:', {
        total_price: totalPriceWithoutProtection,
        items_count: navidiumItems.length,
        country_name: countryName,
        shop_url: window.location.hostname,
      })

      const response = await fetch(url, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          store_id: `5b8cd47a-21de-4c80-b862-5bace93b79ee`,
          total_price: totalPriceWithoutProtection,
          items: navidiumItems,
          country_name: countryName,
          shop_url: window.location.hostname,
        }),
      })

      if (!response.ok) {
        throw new Error(`HTTP error! Status: ${response.status}`)
      }

      const navidiumData = await response.json()
      console.log('[qc] ✅ STEP 4: Response received by script from our backend')
      console.log('[qc] Response status code:', navidiumData.statusCode || 'N/A')
      console.log(
        '[qc] 💰 PRICE TRACE - Protection price received:',
        navidiumData.data?.price,
      )
      console.log(
        '[qc] 🛡️ PRICE TRACE - Protection variant ID:',
        navidiumData.data?.variant_id,
      )
      console.log('[qc] Full response:', navidiumData)

      // Store Navidium response globally
      window.qcNavidiumResponse = navidiumData
      console.log('[qc] 💾 Navidium response stored in window.qcNavidiumResponse')

      return navidiumData
    } catch (error) {
      logger.error('Error in Navidium backend call', error, {
        url,
        storeId: `5b8cd47a-21de-4c80-b862-5bace93b79ee`,
        itemsCount: navidiumItems.length
      })
      window.qcNavidiumResponse = null
      return null
    }
  }

  // Function to remove Navidium protection from Shopify cart
  async function removeNavidiumProtectionFromCart() {
    try {
      console.log(
        '[qc] 🗑️ CLEANUP FUNCTION CALLED - Removing Navidium protection from cart...',
      )

      // Get current cart to find protection items
      console.log('[qc] 🗑️ Step 1: Fetching current cart state...')
      const cartResponse = await fetch('/cart.js')
      if (!cartResponse.ok) {
        throw new Error(`Failed to fetch cart: ${cartResponse.status}`)
      }

      const cartData = await cartResponse.json()
      console.log('[qc] 🗑️ Step 2: Cart fetched, analyzing items...', {
        total_items: cartData.items?.length || 0,
        items_summary:
          cartData.items?.map((item) => ({
            title: item.title,
            variant_id: item.variant_id,
            has_protection_property: !!item.properties?._navidium_protection,
            protection_value: item.properties?._navidium_protection,
          })) || [],
      })

      const protectionItems =
        cartData.items?.filter(
          (item) => item.properties?._navidium_protection === 'true',
        ) || []

      console.log('[qc] 🗑️ Step 3: Protection items identified:', {
        protection_items_count: protectionItems.length,
        protection_items: protectionItems.map((item) => ({
          title: item.title,
          variant_id: item.variant_id,
          price: item.price / 100,
        })),
      })

      if (protectionItems.length === 0) {
        console.log(
          '[qc] ℹ️ No Navidium protection items found in cart - cleanup not needed',
        )
        return true
      }

      console.log(
        '[qc] 🗑️ Step 4: Starting removal of',
        protectionItems.length,
        'protection item(s)',
      )

      // Remove each protection item by setting quantity to 0
      for (const item of protectionItems) {
        console.log('[qc] 🗑️ Removing protection item:', item.variant_id)
        const removeResponse = await fetch('/cart/change.js', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            id: String(item.variant_id), // Ensure variant_id is sent as string
            quantity: 0,
          }),
        })

        if (!removeResponse.ok) {
          console.warn(
            '[qc] ⚠️ Failed to remove protection item:',
            item.variant_id,
            'Status:',
            removeResponse.status,
          )
          const errorText = await removeResponse.text()
          console.warn('[qc] ⚠️ Error response:', errorText)
        } else {
          console.log('[qc] ✅ Successfully removed protection item:', {
            variant_id: item.variant_id,
            title: item.title,
            price: item.price / 100,
          })
        }
      }

      // Verify removal by checking cart again
      console.log('[qc] 🗑️ Step 5: Verifying protection items were removed...')
      const verifyResponse = await fetch('/cart.js')
      const verifyData = await verifyResponse.json()
      const remainingProtection =
        verifyData.items?.filter(
          (item) => item.properties?._navidium_protection === 'true',
        ) || []

      console.log('[qc] 🗑️ Step 6: Verification complete:', {
        remaining_protection_items: remainingProtection.length,
        total_cart_items_after: verifyData.items?.length || 0,
      })

      console.log('[qc] ✅ Navidium protection removal process completed')
      return true
    } catch (error) {
      logger.error('Error in removeNavidiumProtectionFromCart', error)
      // Don't fail the entire process if protection removal fails
      return false
    }
  }

  // Immediate Navidium state reset function - called on any user action
  function resetNavidiumState(reason) {
    console.log(`[qc] 🔄 CHECKING RESET: ${reason}`)
    const wasBlocked = window.qcNavidiumCleanupInProgress

    // Always clear the cleanup flag to prevent blocking
    if (wasBlocked) {
      window.qcNavidiumCleanupInProgress = false
      console.log(`[qc] 🔄 Cleared cleanup flag due to: ${reason}`)
    }

    // Only clear response if we're specifically told it's stale
    // Don't clear fresh responses that we might still need
    console.log(`[qc] 🔄 Response preserved for immediate use`)
  }

  // Centralized Navidium cleanup function
  async function performNavidiumCleanup(trigger) {
    console.log(`[qc] 🧹 CLEANUP TRIGGERED BY: ${trigger}`)
    console.log('[qc] 🔥 Current state:', {
      hasNavidiumApp: hasNavidiumApp(),
      hasNavidiumResponse: !!window.qcNavidiumResponse,
      navidiumResponseData: window.qcNavidiumResponse?.data || 'none',
    })

    // Set flag to prevent re-adding protection during cleanup
    window.qcNavidiumCleanupInProgress = true
    console.log('[qc] 🧹 Set cleanup flag to prevent re-add during cleanup')

    // Log cart state BEFORE cleanup
    try {
      console.log('[qc] 🧹 STEP A: Checking cart state BEFORE cleanup...')
      const preCleanupResponse = await fetch('/cart.js')
      const preCleanupCart = await preCleanupResponse.json()
      console.log('[qc] 🧹 PRE-CLEANUP CART:', {
        total_items: preCleanupCart.items?.length || 0,
        protection_items:
          preCleanupCart.items?.filter(
            (item) => item.properties?._navidium_protection === 'true',
          ).length || 0,
        all_items:
          preCleanupCart.items?.map((item) => ({
            title: item.title,
            variant_id: item.variant_id,
            is_protection: item.properties?._navidium_protection === 'true',
          })) || [],
      })
    } catch (error) {
      console.error('[qc] ❌ Failed to fetch pre-cleanup cart state:', error)
    }

    if (hasNavidiumApp() && window.qcNavidiumResponse) {
      console.log('[qc] 🧹 CONDITIONS MET - Starting Navidium protection cleanup')

      try {
        await removeNavidiumProtectionFromCart()
        console.log('[qc] ✅ Navidium protection background cleanup completed')

        // Clear the stored response since we're removing the protection
        window.qcNavidiumResponse = null
        console.log('[qc] 🧹 Cleared window.qcNavidiumResponse')

        // Clear cleanup flag immediately - user actions will reset state anyway
        window.qcNavidiumCleanupInProgress = false
        console.log(
          '[qc] 🧹 Cleared cleanup flag - next user action will get fresh state',
        )
      } catch (error) {
        console.error('[qc] ⚠️ Failed to remove Navidium protection on close:', error)
        // Clear flag even on error to prevent blocking future checkouts
        window.qcNavidiumCleanupInProgress = false
        console.log(
          '[qc] 🧹 Cleared cleanup flag after error to prevent blocking future checkouts',
        )
      }
    } else {
      console.log('[qc] ❌ CONDITIONS NOT MET - Skipping cleanup:', {
        hasNavidiumApp: hasNavidiumApp(),
        hasNavidiumResponse: !!window.qcNavidiumResponse,
      })
    }
  }

  // DEBUGGING: Expose test functions to global window for manual testing
  window.qcTestNavidiumCleanup = removeNavidiumProtectionFromCart
  window.qcTestNavidiumApp = hasNavidiumApp
  window.qcTestNavidiumResponse = () => window.qcNavidiumResponse
  window.qcPerformNavidiumCleanup = performNavidiumCleanup
  window.qcResetNavidiumState = resetNavidiumState

  // Function to add Navidium protection variant to Shopify cart
  async function addNavidiumProtectionToCart() {
    if (!window.qcNavidiumResponse || !window.qcNavidiumResponse.data) {
      console.log('[qc] 🚫 No Navidium protection data available')
      return false
    }

    const variantId = window.qcNavidiumResponse.data.variant_id
    if (!variantId) {
      console.log('[qc] 🚫 No protection variant ID in Navidium response')
      return false
    }

    // Check if protection is enabled
    if (!window.qcNavidiumResponse.data.widget_display_status) {
      console.log('[qc] 🚫 Navidium protection widget disabled')
      return false
    }

    // Note: We no longer check for existing protection since we always remove before adding

    try {
      console.log('[qc] 🛡️ STEP 5: Adding protection item to Shopify cart')
      console.log('[qc] 💰 PRICE TRACE - Protection variant ID to add:', variantId)
      console.log(
        '[qc] 💰 PRICE TRACE - Expected protection price:',
        window.qcNavidiumResponse.data.price,
      )

      const response = await fetch('/cart/add.js', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          id: variantId,
          quantity: 1,
          properties: {
            _navidium_protection: 'true',
          },
        }),
      })

      if (!response.ok) {
        // If it's a 422 (variant already in cart), that's actually OK
        if (response.status === 422) {
          console.log('[qc] ℹ️ Protection variant already in cart (422 response)')
          return true
        }
        throw new Error(`HTTP error! Status: ${response.status}`)
      }

      const result = await response.json()
      console.log('[qc] ✅ Protection item added to cart successfully')
      console.log('[qc] 💰 PRICE TRACE - Added protection details:', {
        variant_id: result.variant_id,
        title: result.title,
        price_cents: result.price,
        price_dollars: result.price / 100,
        quantity: result.quantity,
      })
      console.log(
        '[qc] 💰 PRICE TRACE - Does added price match expected?',
        'Expected:',
        window.qcNavidiumResponse.data.price,
        'Added:',
        result.price / 100,
        'Match:',
        window.qcNavidiumResponse.data.price == result.price / 100,
      )

      return true
    } catch (error) {
      logger.error('Error adding Navidium protection to cart', error, {
        variantId: window.qcNavidiumResponse?.data?.variant_id
      })

      // Don't fail the entire checkout process if protection can't be added
      console.log('[qc] ⚠️ Continuing with checkout despite protection add failure')
      return false
    }
  }

  // gift note url param (buttonsbebe.com)
  // https://help.shopify.com/en/manual/online-store/themes/themes-by-shopify/vintage-themes/customizing-vintage-themes/add-gift-wrap-option
  const getGiftWrappingCheckboxStatus = () => {
    const checkBox = document.getElementById('gift__wrapping-')
    if (checkBox !== null) {
      return checkBox.checked
    }

    return false
  }

  const getGiftWrappingNoteMessage = () => {
    const message = document.getElementById('gift__note')

    if (message !== null) {
      return replaceBreakingCharacters(message.value)
    }

    return ''
  }

  // function to retrieve GA params from url
  const getGAUrlParams = () => {
    const searchParams = window.location.href.split('?')[1]

    const gclid = new URLSearchParams(searchParams).get('gclid')
    const utm_id = new URLSearchParams(searchParams).get('utm_id')
    const utm_campaign = new URLSearchParams(searchParams).get('utm_campaign')
    const utm_source = new URLSearchParams(searchParams).get('utm_source')
    const utm_medium = new URLSearchParams(searchParams).get('utm_medium')
    const utm_content = new URLSearchParams(searchParams).get('utm_content')
    const utm_term = new URLSearchParams(searchParams).get('utm_term')

    return {
      ...(gclid && { gclid }),
      ...(utm_id && { utm_id }),
      ...(utm_campaign && { utm_campaign }),
      ...(utm_source && { utm_source }),
      ...(utm_medium && { utm_medium }),
      ...(utm_content && { utm_content }),
      ...(utm_term && { utm_term }),
    }
  }

  const setGaParamsToCookie = (gaParams) => {
    // set cookie for each parameter of gaParams object
    // where ket is the name of the cookie and value is the value of the cookie
    for (const [key, value] of Object.entries(gaParams)) {
      document.cookie = `${key}=${value};path=/;max-age=31536000;`
    }
  }

  const getGaParamsFromCookie = () => {
    const gaParams = {}

    // get all cookies
    const cookies = document.cookie.split(';')

    // iterate through cookies
    for (let i = 0; i < cookies.length; i++) {
      const cookie = cookies[i].trim()

      // check if cookie name starts with 'utm_'
      if (cookie.startsWith('utm_') || cookie.startsWith('gclid')) {
        const cookieName = cookie.split('=')[0]
        const cookieValue = cookie.split('=')[1]

        // add cookie to gaParams object
        gaParams[cookieName] = cookieValue
      }
    }

    return gaParams
  }

  // function to convert object to string which is passed to iframe source
  const paramsObjectToString = (object) => {
    let string = ''

    for (const [key, value] of Object.entries(object)) {
      string += `&${key}=${value}`
    }

    return string
  }

  const gaUrlParams = getGAUrlParams()
  setGaParamsToCookie(gaUrlParams)

  //func to get GA client_id from cookie directly if gtag function failed
  function getGaClientIdFromCookies() {
    const gaClientIdCookieValue = document.cookie
      .split('; ')
      .find((row) => row.startsWith('_ga'))
      ?.split('=')[1]

    const regex = /GA1\.1\.(\d+\.\d+)/
    const match = gaClientIdCookieValue?.match(regex)

    if (match && match[1]) {
      console.debug('[qc] extracted client_id directly from cookie:', match?.[1])
      return match[1] // client_id
    } else {
      console.debug('[qc] failed to get ga client_id from cookie')
      return ''
    }
  }

  //func to get GA session_id from cookie directly if gtag function failed
  function getGaSessionIdFromCookies() {
    const id = ``.slice(2)
    const pattern = new RegExp('_ga_' + id + '=GS\\d\\.\\d\\.(.+?)(?:;|$)')
    const match = document.cookie.match(pattern)
    const parts = match?.[1].split('.')

    if (!parts) {
      console.debug('[qc] failed to get ga session_id from cookie')
      return ''
    }

    console.debug('[qc] extracted ga session_id directly from cookie:', parts?.[0])
    return parts?.[0] // session id
  }

  let client_id = ''
  let session_id = ''
  //attempt to extract gaClientId with gtag function
  setTimeout(() => {
    console.debug('[qc] attempting to extract client_id and session_id with gtag')

    gtag('get', ``, 'client_id', (id) => {
      client_id = id
      console.debug('[qc] successfuly extracted client_id with gtag:', client_id)
    })

    gtag('get', ``, 'session_id', (id) => {
      session_id = id
      console.debug('[qc] successfuly extracted session_id with gtag:', session_id)
    })
  }, 1500)

  /**
   * getCart is used to get user cart contents
   * @return {Promise<Array<{ variantId: string, quantity: number, properties: {} }>> | undefined}
   */
  window.qcGetCart = () => {
    const isJdWatchesUrl = window.location.href.includes('jdwatchesny.com');
    const isProductPage = window.location.href.includes('collections/')
    // For this store all checkout related stuff is moved to another place
    if(isJdWatchesUrl && isProductPage) {
      throw new Error("Disabled For JD Watches");
    }

    let lastCartData = null // Declare outside promise chain to track cart data

    return fetch('/cart.js')
      .then((res) => {
        if (!res.ok) {
          throw new Error('cart.js fetch request failed')
        }
        return res.json()
      })
      .then((cart) => {
        lastCartData = cart // Store initial cart data
        if (!cart.hasOwnProperty('items') || cart.items.length === 0) {
          return fetch('/cart.js')
            .then((refetchedRes) => {
              if (!refetchedRes.ok) {
                throw new Error('cart.js refetch request failed')
              }
              return refetchedRes.json()
            })
            .then((refetchedCart) => {
              lastCartData = refetchedCart // Update with retry cart data
              if (
                !refetchedCart.hasOwnProperty('items') ||
                refetchedCart.items.length === 0
              ) {
                throw new Error('Cart object is not valid after fetch retry')
              }

              return refetchedCart
            })
        }
        return cart
      })
      .then((cart) => {
        lastCartData = cart // Store final cart data

        // check for digital product
        if (!cart.items.some((t) => t.requires_shipping)) {
          throw new Error(
            `No products that require shipping: ${JSON.stringify(
              cart.items.map((t) => ({
                variantId: t.variant_id.toString(),
                quantity: t.quantity,
                properties: t.properties,
                requires_shipping: t.requires_shipping,
              })),
            )}`,
          )
        }

        // return products in the format that we need
        return cart.items.map((t) => ({
          variantId: t.variant_id.toString(),
          quantity: t.quantity,
          properties: t.properties,
        }))
      })
      .catch((error) => {
        console.error('[qc] cart error:', error.message)

        // Sneaker Bar: ~97% mobile users triggering checkout with empty cart.
        // Root cause is on their storefront/theme side (checkout button accessible with empty cart on mobile),
        // not in QC script. Using store ID because URL check fails when accessed via custom domain.
        const isSneakerBar = `5b8cd47a-21de-4c80-b862-5bace93b79ee` === '3140cbbc-ade5-455b-b4fc-59caa01023f4';
        const isBot = /bot|crawl|spider|storebot/i.test(userAgent);
        // Disabled for bots/crawlers (e.g. Storebot-Google) that trigger checkout with empty carts
        if(!isJdWatchesUrl && !isSneakerBar && !isBot) {
          sendMonitoringPostRequest({
            storeId: `5b8cd47a-21de-4c80-b862-5bace93b79ee`,
            reason: error.message,
            details: JSON.stringify({
              userAgent,
              ...(lastCartData && { invalidCart: lastCartData }),
            }),
          })
        }

        throw new Error(error.message)
      })
  }

  /**
   * getProduct is used to get the currently viewed product.
   * @param targetElement any
   * @return {Promise<{ variantId: string, quantity: number, properties: {} }>}
   */
  window.qcGetProduct = (targetElement) => {
    // productTitleSelector contains selector for tag with product title
    // <h2> Product name </h2>
    const productTitleSelector = `h1, h2, .h1, .h2`
    let productName = window.location.pathname.split('/').pop()

    if (productName === '' && productTitleSelector !== '') {
      // if no product name in url find title of product in DOM and make it from "Product name" to "Product-name"
      productName = targetElement
        .closest('.shopify-section')
        .querySelector(productTitleSelector)
        .innerText.trim()
        .replace(/&nbsp;/g, '')
        .replace(/\s/g, '-')
        .replace('"', '')
        .replace('.', '-')
    }

    // get raw entries for selected product
    const entries = Array.from(
      new FormData(targetElement.closest('form[action^="/cart/add"]')).entries(),
    )

    // extract properties from entries
    const properties = entries.reduce((acc, [key, value]) => {
      // parce property key name
      if (key.startsWith('properties[')) {
        const newKey = key.replace('properties[', '').replace(']', '')

        // add key/value pair to the properties object
        acc = { ...acc, [newKey]: value }
      }

      // return array of properties
      return acc
    }, {})

    const variantId = entries.find((i) => i[0] === 'id')[1]
    // get quantity input
    const quantityInput = document.querySelector(`input[name=quantity]`)

    return fetch(`/products/${productName}.js`)
      .then((r) => r.json())
      .then((product) => {
        // check for digital product
        if (!product.variants[0].requires_shipping) {
          return sendMonitoringPostRequest({
            storeId: `5b8cd47a-21de-4c80-b862-5bace93b79ee`,
            reason: 'No products that require shipping [buy now purchase]',
            isExpected: true,
            details: JSON.stringify({ product, userAgent }),
          }).finally(() => window.qcShowDefaultCheckout(element))
        }

        const formattedProduct = {
          variantId,
          quantity: Number((quantityInput || {}).value || 1),
          properties,
        }

        // check for digital product
        if (!product.variants[0].requires_shipping) {
          return sendMonitoringPostRequest({
            storeId: `5b8cd47a-21de-4c80-b862-5bace93b79ee`,
            products: JSON.stringify(product),
            reason: 'No products that require shipping [buy now purchase]',
          }).finally(() => window.qcShowDefaultCheckout(element))
        }

        return formattedProduct
      })
  }

  /**
   * openCheckout is used to open QuickCheckout page popup
   * @param element any
   * @param products Array<{ variantId: string, quantity: number, properies: any[] }> list of products
   * @param clearCartAfterComplete boolean | undefined
   */
  window.qcOpenCheckout = ({ element, products, clearCartAfterComplete }) => {
    console.debug(`[qc] opening checkout`, products)
    
    // Start session recording when checkout opens
    if (typeof posthog !== 'undefined' && posthog.startSessionRecording) {
      try {
        posthog.startSessionRecording()
        logger.info('Session recording started for checkout', {
          products_count: products?.length || 0,
          has_discount: discount.code !== '' && discount.code !== undefined
        })
      } catch (error) {
        logger.error('Failed to start session recording', error)
      }
    }
    
    if (discount.code !== '' && discount.code !== undefined) {
      console.debug(`[qc] pre-applied discount:`, discount.code)
    }

    // remove search params from location.href and location.search to prevent parsing issues
    const hrefRaw = window.location.href.split('?')[0]
    const href = removeHashFromUrl(hrefRaw)

    // stringify products
    const formattedProducts = formatProducts(products)
    const productsString = JSON.stringify(formattedProducts)

    // check if gaClientId and gaSessionId are already extracted with gtag
    // if not, try to extract them from cookies
    if (client_id === '') {
      client_id = getGaClientIdFromCookies() // already string
    }

    if (session_id === '') {
      session_id = getGaSessionIdFromCookies() // already string
    }

    const gaParams = getGaParamsFromCookie()

    // it any GA params found, pass them to iframe later
    const gaParamsString = gaParams !== '{}' ? paramsObjectToString(gaParams) : ''
    const gaClientIdString = client_id !== '' ? `&client_id=${client_id}` : ''
    const gaSessionIdString = session_id !== '' ? `&session_id=${session_id}` : ''

    const isGiftNoteAdded = getGiftWrappingCheckboxStatus() // boolean
    const giftNoteMessage = getGiftWrappingNoteMessage() // string

    const giftNoteString =
      isGiftNoteAdded && giftNoteMessage !== '' ? `&gift_note=${giftNoteMessage}` : ''

    // check for Navidium app and get shop domain
    const navidiumEnabled = hasNavidiumApp()
    const shopDomain = window.location.hostname
    // Include Navidium response data if available
    let navidiumString = ''
    if (navidiumEnabled) {
      navidiumString = `&navidium_enabled=true&shop_domain=${encodeURIComponent(
        shopDomain,
      )}`

      // Add Navidium response data if available
      if (window.qcNavidiumResponse) {
        navidiumString += `&navidium_data=${encodeURIComponent(
          JSON.stringify(window.qcNavidiumResponse),
        )}`
        console.log('[qc] Including Navidium response data in iframe URL')
      }
    }

    console.log(
      '[qc] 🎯 Checkout opening with Navidium status:',
      navidiumEnabled ? 'ENABLED' : 'DISABLED',
    )
    if (navidiumEnabled) {
      console.log('[qc] Navidium protection data available:', !!window.qcNavidiumResponse)
      if (window.qcNavidiumResponse) {
        console.log('[qc] Protection plan to be applied:', {
          variant_id: window.qcNavidiumResponse.data?.variant_id,
          price: window.qcNavidiumResponse.data?.price,
          status: window.qcNavidiumResponse.data?.widget_display_status,
        })
      }
    }
    console.log('[qc] Iframe URL parameters:', {
      navidiumEnabled,
      shopDomain,
      storeId: '5b8cd47a-21de-4c80-b862-5bace93b79ee',
      products_count: formattedProducts.length,
      has_navidium_data: !!window.qcNavidiumResponse,
    })

    // get discount code
    let discountString = ''
    if (discount.code !== '') {
      const formattedDiscountCode = replaceBreakingCharacters(discount.code)

      discountString =
        formattedDiscountCode !== ''
          ? `&discount=${JSON.stringify(formattedDiscountCode)}`
          : ''
    }

    // create iframe
    let iframe = document.createElement('iframe')
    const iframeSource = `https://checkout.qcpg.cc/delivery?storeId=5b8cd47a-21de-4c80-b862-5bace93b79ee&href=${href}&products=${productsString}${discountString}${gaParamsString}${gaClientIdString}${gaSessionIdString}${giftNoteString}${navidiumString}`

    iframe.src = iframeSource

    // check Google Analytics
    if (window.ga) {
      // get track id
      ga((tracker) => {
        iframe.src += '&clientId=' + tracker.get('clientId')
      })

      // get Google analytics "_ga" param for cross domain tracking
      if (window.gaplugins) {
        const tracker = window.ga.getAll()[0]
        const linker = new window.gaplugins.Linker(tracker)
        iframe.src = linker.decorate(iframe.src)
      }
    }

    iframe.style.cssText =
      'width: 100%; height:100%; position:fixed; top:0; left:0; z-index:10000000000; border:none;'
    document.body.style.overflow = 'hidden'

    // listen to messages from iframe
    window.addEventListener('message', async (message) => {
      // 🔥 DEBUG: Log RAW message data to see exactly what iframe is sending
      console.log('[qc] 🔥 RAW MESSAGE DEBUG:', {
        origin: message.origin,
        source: message.source === iframe.contentWindow ? 'OUR_IFRAME' : 'OTHER_SOURCE',
        raw_data: message.data,
        data_type: typeof message.data,
        is_string: typeof message.data === 'string',
        parsed_attempt:
          typeof message.data === 'string'
            ? (() => {
                try {
                  return JSON.parse(message.data)
                } catch (e) {
                  return 'PARSE_ERROR: ' + e.message
                }
              })()
            : message.data,
      })

      // Only process messages from our checkout iframe
      if (message.source !== iframe.contentWindow) {
        console.log('[qc] 🔥 IGNORING MESSAGE - Not from our iframe')
        return
      }

      console.debug('received message', { message })

      const {
        type,
        href,
        reason,
        products,
        errorMessage,
        redirectUrl,
        isExpected,
        checkoutID,
      } = typeof message.data === 'string' ? JSON.parse(message.data) : message.data || {}

      // 🔥 DEBUG: Log extracted message type
      console.log('[qc] 🔥 EXTRACTED MESSAGE TYPE:', type, 'Full parsed data:', {
        type,
        href,
        reason,
        products,
        errorMessage,
        redirectUrl,
        isExpected,
      })

      if (type === 'close') {
        console.log('[qc] 🔥 CLOSE EVENT RECEIVED - Starting cleanup process')
        console.log('[qc] 🔥 Current state:', {
          hasNavidiumApp: hasNavidiumApp(),
          hasNavidiumResponse: !!window.qcNavidiumResponse,
          navidiumResponseData: window.qcNavidiumResponse?.data || 'none',
        })

        // Stop session recording when checkout closes
        if (typeof posthog !== 'undefined' && posthog.stopSessionRecording) {
          try {
            posthog.stopSessionRecording()
            logger.info('Session recording stopped - checkout closed')
          } catch (error) {
            logger.error('Failed to stop session recording', error)
          }
        }

        document.body.removeChild(iframe)
        element.classList.remove('disabled')
        element.removeAttribute('disabled')
        document.body.style.overflow = 'auto'

        // Clean up Navidium protection when checkout is closed without purchase
        performNavidiumCleanup('CLOSE_EVENT')
      } else if (type === 'error') {
        console.debug('closing checkout, because error occurred')
        console.log('[qc] 🔍 ERROR: Received error from iframe, reason:', reason)
        
        // Stop session recording on error
        if (typeof posthog !== 'undefined' && posthog.stopSessionRecording) {
          try {
            posthog.stopSessionRecording()
            logger.info('Session recording stopped - checkout error', { reason, errorMessage })
          } catch (error) {
            logger.error('Failed to stop session recording', error)
          }
        }
        
        document.body.removeChild(iframe)
        document.body.style.overflow = 'auto'

        // Clean up Navidium protection on error too
        performNavidiumCleanup('ERROR_EVENT')
        // call click event again with default behavior

        // do not send monitoring request if error is caused by create checkout request
        if (reason !== '[app] Create checkout request failed') {
          console.log(
            '[qc] 🔍 ERROR: Non-checkout-creation error, sending monitoring then fallback',
          )
          return sendMonitoringPostRequest({
            storeId: `5b8cd47a-21de-4c80-b862-5bace93b79ee`,
            checkoutId: checkoutID,
            reason: reason + ` => ${errorMessage}`,
            isExpected: isExpected || false,
            details: JSON.stringify({ products, userAgent }),
          }).finally(() => window.qcShowDefaultCheckout(element, redirectUrl))
        }

        console.log(
          '[qc] 🔍 ERROR: Checkout creation failed, direct fallback without monitoring',
        )
        return window.qcShowDefaultCheckout(element)
      } else if (type === 'open_default') {
        // Stop session recording when redirecting to default checkout
        if (typeof posthog !== 'undefined' && posthog.stopSessionRecording) {
          try {
            posthog.stopSessionRecording()
            logger.info('Session recording stopped - redirecting to default checkout')
          } catch (error) {
            logger.error('Failed to stop session recording', error)
          }
        }
        
        document.body.removeChild(iframe)
        document.body.style.overflow = 'auto'

        // Skip all Navidium logic for open_default to ensure immediate redirect
        console.log(
          '[qc] 🚀 Open default requested - redirecting immediately without Navidium cleanup',
        )

        // Always redirect immediately - don't wait for Navidium logic
        return sendMonitoringPostRequest({
          storeId: `5b8cd47a-21de-4c80-b862-5bace93b79ee`,
          checkoutId: checkoutID,
          reason,
          isExpected: true,
          details: JSON.stringify({ products, userAgent }),
        }).finally(() => window.qcShowDefaultCheckout(element, redirectUrl))
      } else if (type === 'purchase') {
        // clear cart if needed
        if (clearCartAfterComplete) {
          fetch('/cart/clear.js')
        }
        resetDiscount()
      } else if (type === 'navigate') {
        window.location.href = href
      }
    })

    // add iframe to document
    document.body.appendChild(iframe)
  }

  window.QC_SHOW_DEFAULT = false

  // CLICK HANDLER
  function handler(event) {
    console.log(
      '[qc] 🔍 HANDLER: Click received, QC_SHOW_DEFAULT:',
      window.QC_SHOW_DEFAULT,
      'isTrusted:',
      event.isTrusted,
    )

    if (event.target.ariaDisabled === 'true') {
      return
    }

    // prevent undtrusted clicks from running the handler if needed
    if (event.isTrusted === false && areNotTrustedClicksDisallowed === true) {
      console.debug('[qc] untrusted clicks are disallowed on this domain')

      return
    }

    // IMMEDIATE RESET: Any click on checkout/buy buttons resets Navidium state
    resetNavidiumState('User clicked checkout/buy button')

    const checkoutButtonSelectors = `[name='checkout'],[name='Checkout'],[class*='checkout-btn'],[class*='btn-checkout'],[class*='checkout-button'],[class*='button-checkout'],[class*='carthook_checkout'],[class*='action_button'],.button.checkout`
      .split(',')
      .map((t) => t.trim())
    const buyNowButtonClasses = `shopify-payment-button__button--unbranded,shopify-payment-button__more-options`.split(',').map((t) => t.trim())

    // if click is on an element that contains .qc-replace tag,
    // intercept the click and show our checkout instead
    for (const element of event.path) {
      const isCheckOut = checkoutButtonSelectors.some((selector) =>
        selector === ''
          ? false
          : element.parentElement?.querySelector(selector) === element,
      )

      const isBuyNow = buyNowButtonClasses.some((className) =>
        className === '' ? false : element.classList?.contains(className),
      )

      if (isCheckOut || isBuyNow) {
        console.log(
          '[qc] 🔍 HANDLER: Checkout button detected, QC_SHOW_DEFAULT:',
          window.QC_SHOW_DEFAULT,
        )

        // If QC_SHOW_DEFAULT is true, don't intercept - let native checkout work
        if (window.QC_SHOW_DEFAULT) {
          console.log(
            '[qc] ✅ HANDLER: Allowing native checkout (QC_SHOW_DEFAULT was true)',
          )
          window.QC_SHOW_DEFAULT = false
          return // Don't intercept this click
        }

        console.log('[qc] 🔍 HANDLER: Intercepting for QuickCheckout')
        event.stopImmediatePropagation()
        event.preventDefault()
        element.classList.add('disabled')
        element.setAttribute('disabled', '')
      }

      if (isCheckOut) {
        console.debug('[qc] detected "check out" click')

        let defaultCheckoutOpenReason = ''

        // set reason for paylater on 4mdmedical.myshopify.com cases
        const selectElement = document.getElementById('CML_payment')
        if (selectElement !== null) {
          if (selectElement.value === 'pay_later') {
            console.debug('[qc] paylater selected; proceed to the default checkout')
            defaultCheckoutOpenReason = 'Paylater option selected'
          }
        }

        // set reason for store pickup on littlecanadian.ca
        const isPickupMethodChosen = document.querySelector(
          'div.checkoutMethodContainer.pickup',
        )
        if (isPickupMethodChosen) {
          console.debug('[qc] store pickup selected; proceed to the default checkout')
          defaultCheckoutOpenReason = 'Store pickup option selected'
        }

        // Store original button text for restoration
        if (!element.getAttribute('data-original-text')) {
          element.setAttribute('data-original-text', element.textContent)
        }

        // First add Navidium protection if available, then get cart and checkout
        const processCheckout = async () => {
          try {
            // State already reset by click handler - no need for complex flag management

            // Check if this is the "without checkout" button that should skip protection
            const isWithoutProtectionButton = element.id === 'nvd-without-checkout-btn'

            // FORCE REMOVAL: If "without protection" clicked, ensure any existing protection is removed first
            if (isWithoutProtectionButton && hasNavidiumApp()) {
              console.log(
                '[qc] 🚫 "Without protection" clicked - force removing any existing protection',
              )
              element.textContent = 'Preparing checkout...' // Show loading state

              try {
                await removeNavidiumProtectionFromCart()
                console.log(
                  '[qc] ✅ Forced protection removal completed for "without protection"',
                )
              } catch (error) {
                console.error('[qc] ❌ Failed to force remove protection:', error)
              } finally {
                element.textContent =
                  element.getAttribute('data-original-text') || 'Checkout' // Restore text
              }
            }

            // Add Navidium protection to cart if available and user did not click "without protection" button
            if (
              hasNavidiumApp() &&
              window.qcNavidiumResponse &&
              !isWithoutProtectionButton
            ) {
              console.log(
                '[qc] 🛡️ Regular checkout clicked - ensuring protection is added',
              )
              element.textContent = 'Opening checkout with protection...' // Show loading state

              try {
                // First remove any existing protection to ensure fresh calculation
                console.log('[qc] 🧹 Removing existing protection before adding new...')
                await removeNavidiumProtectionFromCart()

                // Then add the new protection with updated amount
                console.log('[qc] 🛡️ Adding fresh Navidium protection...')
                const protectionAdded = await addNavidiumProtectionToCart()

                if (protectionAdded) {
                  console.log('[qc] ✅ Navidium protection added successfully')
                } else {
                  console.log(
                    '[qc] ⚠️ Navidium protection not added, continuing with checkout',
                  )
                }
              } catch (error) {
                console.error('[qc] ❌ Failed to add protection:', error)
              } finally {
                element.textContent =
                  element.getAttribute('data-original-text') || 'Checkout' // Restore text
              }
            } else if (isWithoutProtectionButton) {
              console.log(
                '[qc] ⏭️ Skipping Navidium protection - without-checkout button clicked',
              )
            } else {
              console.log('[qc] ⏭️ No Navidium protection to add')
            }

            // STEP 6: Get updated cart after adding protection
            console.log('[qc] 📦 STEP 6: Fetching updated cart after protection added')
            const products = await window.qcGetCart()

            console.log(
              '[qc] 💰 PRICE TRACE - Final cart before checkout:',
              products.map((p) => ({
                variantId: p.variantId,
                quantity: p.quantity,
                properties: p.properties,
              })),
            )

            if (!products) {
              return window.qcShowDefaultCheckout(element)
            }

            if (defaultCheckoutOpenReason !== '') {
              return sendMonitoringPostRequest({
                storeId: `5b8cd47a-21de-4c80-b862-5bace93b79ee`,
                reason: defaultCheckoutOpenReason,
                isExpected: true,
                details: JSON.stringify({ products, userAgent }),
              }).finally(() => window.qcShowDefaultCheckout(element))
            }

            console.log('[qc] 🚀 Opening checkout with', products.length, 'products')
            window.qcOpenCheckout({
              element,
              products,
              clearCartAfterComplete: true,
            })
          } catch (error) {
            console.error('[qc] ❌ Error in checkout process:', error)
            return window.qcShowDefaultCheckout(element)
          }
        }

        processCheckout()
        break
      }

      if (isBuyNow) {
        console.debug('[qc] detected "buy now" click')
        window
          .qcGetProduct(element)
          .then((product) => {
            if (!product) {
              return window.qcShowDefaultCheckout(element)
            }

            window.qcOpenCheckout({
              element,
              products: [product],
            })
          })
          .catch((error) => {
            console.error('[qc] error', error.message)

            return window.qcShowDefaultCheckout(element)
          })
        break
      }
    }
  }

  // Intercept fetch to track cart.js GET calls
  const originalFetch = window.fetch
  window.fetch = function (...args) {
    const [url, options] = args

    if (typeof url === 'string' && url.includes('/cart.js')) {
      // Check if it's a GET request (default method is GET)
      const method = options?.method || 'GET'
      if (method === 'GET') {
        console.log('[qc] 🛒 Cart.js GET request intercepted:', url)
        console.log('[qc] Request method:', method)
        console.log('[qc] Request timestamp:', new Date().toISOString())

        return originalFetch
          .apply(this, args)
          .then((response) => {
            const clonedResponse = response.clone()
            clonedResponse
              .json()
              .then(async (cartData) => {
                console.log('[qc] ✅ Cart data successfully retrieved')
                console.log('[qc] Cart details:', {
                  item_count: cartData.item_count,
                  total_items: cartData.items?.length || 0,
                  total_price: cartData.total_price,
                  total_price_usd: cartData.total_price / 100,
                  currency: cartData.currency,
                  token: cartData.token,
                })

                // Log each item in the cart
                if (cartData.items && cartData.items.length > 0) {
                  console.log('[qc] 📦 Cart items:')
                  cartData.items.forEach((item, index) => {
                    console.log(`[qc]   Item ${index + 1}:`, {
                      title: item.title,
                      variant_id: item.variant_id,
                      quantity: item.quantity,
                      price: item.price / 100,
                      sku: item.sku,
                      product_type: item.product_type,
                    })
                  })
                } else {
                  console.log('[qc] 🛒 Cart is empty')
                }

                // Compare with previous cart state
                if (window.qcLastCartState) {
                  const prevCount = window.qcLastCartState.item_count || 0
                  const currCount = cartData.item_count || 0
                  if (prevCount !== currCount) {
                    console.log(`[qc] 🔄 Cart changed: ${prevCount} → ${currCount} items`)
                    // IMMEDIATE RESET: Cart changes mean we need fresh calculation
                    resetNavidiumState('Cart contents changed')
                    // Clear response since cart changed - need fresh calculation
                    window.qcNavidiumResponse = null
                    console.log(
                      `[qc] 🔄 Cleared response due to cart change - will recalculate`,
                    )
                  }
                }

                // Store cart data in global variable
                window.qcLastCartState = cartData

                // Send cart to Navidium backend if Navidium is present
                const navidiumDetected = hasNavidiumApp()
                console.log('[qc] 🔍 Navidium app detection result:', navidiumDetected)

                if (navidiumDetected && cartData.items && cartData.items.length > 0) {
                  console.log('[qc] 🚀 Initiating Navidium protection calculation...')
                  const navidiumResult = await sendCartToNavidiumBackend(cartData)

                  if (navidiumResult) {
                    console.log('[qc] ✅ Navidium protection calculation complete')
                    console.log('[qc] Protection plan details:', {
                      variant_id: navidiumResult.data?.variant_id,
                      price: navidiumResult.data?.price,
                      widget_display: navidiumResult.data?.widget_display_status,
                    })
                  } else {
                    console.log(
                      '[qc] ❌ Navidium protection calculation failed or returned null',
                    )
                  }
                } else if (
                  navidiumDetected &&
                  (!cartData.items || cartData.items.length === 0)
                ) {
                  console.log('[qc] ⏭️ Skipping Navidium - cart is empty')
                  window.qcNavidiumResponse = null
                } else if (!navidiumDetected) {
                  console.log('[qc] ⏭️ Skipping Navidium - app not detected on store')
                }
              })
              .catch((error) => {
                console.error('[qc] ❌ Error parsing cart.js response:', error)
              })
            return response
          })
          .catch((error) => {
            console.error('[qc] ❌ Error fetching cart.js:', error)
            throw error
          })
      }
    }

    return originalFetch.apply(this, args)
  }

  // track every click
  window.addEventListener('touchstart', handler, true)
  window.addEventListener('click', handler, true)

  // JD Watches / APO custom logic
  // Done to overwrite default store form submission sending logic, and fix native checkout opening problem
  const isJdWatchesUrl = window.location.href.includes('jdwatchesny.com');
  if (isJdWatchesUrl) {
    console.log('[qc] JD watches enabled')

    // Override form.submit for /cart/add forms
    const originalFormSubmit = HTMLFormElement.prototype.submit
    HTMLFormElement.prototype.submit = function () {
      if (this.action?.includes('/cart/add')) {
        console.log('[qc] Intercepting form.submit() to /cart/add')
        handleApoAddToCart(this)
        return
      }
      return originalFormSubmit.call(this)
    }

    // Intercept click on submit buttons inside /cart/add forms
    document.addEventListener(
      'click',
      (e) => {
        const buyNowClasses = `shopify-payment-button__button--unbranded,shopify-payment-button__more-options`.split(',').map((t) => t.trim()).filter(Boolean)
        const buyNowSelector = buyNowClasses.map((cls) => `.${cls}`).join(',')
        const button = buyNowSelector ? e.target.closest(buyNowSelector) : null
        if (!button) return

        const form = button.closest('form')
        if (!form?.action?.includes('/cart/add')) return

        console.log('[qc] Intercepting click on add-to-cart button')
        e.preventDefault()
        e.stopPropagation()
        e.stopImmediatePropagation()

        handleApoAddToCart(form, button)
      },
      true,
    )

    async function handleApoAddToCart(form, button) {
      console.log('[qc] handleApoAddToCart')

      // Disable button
      if (button) {
        button.disabled = true
        button.dataset.originalText = button.textContent
        button.textContent = 'Adding...'
      }

      try {
        const formData = new FormData(form)

        // Extract main product info
        const mainProductId = formData.get('id')
        const quantity = parseInt(formData.get('quantity')) || 1

        console.log('[qc] Main product ID:', mainProductId)
        console.log('[qc] Quantity:', quantity)

        // Find all checked APO option radios with variant IDs
        const checkedOptions = form.querySelectorAll(
          'input[type="radio"]:checked[data-variant-id]',
        )
        console.log('[qc] Found', checkedOptions.length, 'checked APO options')

        // Build items array
        const items = []

        // Add APO option items first (like APO does)
        checkedOptions.forEach((radio) => {
          const variantId = radio.getAttribute('data-variant-id')
          const fieldName = radio.getAttribute('field-name') || radio.getAttribute('name')
          const optionValue = radio.getAttribute('data-option-value') || radio.value

          console.log('[qc] APO option:', fieldName, '=', optionValue, 'variantId:', variantId)

          items.push({
            id: parseInt(variantId),
            quantity: 1,
            properties: {
              _apo_option: `${fieldName}: ${optionValue}`,
              _apo_order: `Added by: ${mainProductId} * ${quantity}`,
            },
          })
        })

        // Build properties for main product
        const mainProperties = {}
        checkedOptions.forEach((radio) => {
          const fieldName = radio.getAttribute('field-name') || radio.getAttribute('name')
          const optionValue = radio.getAttribute('data-option-value') || radio.value
          mainProperties[fieldName] = optionValue
        })
        mainProperties['_apo_order'] = parseInt(mainProductId)

        // Add main product
        items.push({
          id: parseInt(mainProductId),
          quantity: quantity,
          properties: mainProperties,
        })

        console.log('[qc] Items to add:', JSON.stringify(items, null, 2))

        // Add all items to cart
        const response = await fetch('/cart/add.js', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({ items }),
        })

        if (!response.ok) {
          const text = await response.text()
          throw new Error('Failed to add to cart: ' + response.status + ' ' + text)
        }

        const result = await response.json()
        console.log('[qc] Added to cart:', result)

        // Get full cart
        const cartRes = await fetch('/cart.js')
        const cart = await cartRes.json()
        console.log('[qc] Cart:', cart.item_count, 'items')

        if (!cart.items?.length) {
          throw new Error('Cart is empty')
        }

        // Restore button
        if (button) {
          button.disabled = false
          button.textContent = button.dataset.originalText
        }

        // Format products and open checkout
        const products = cart.items.map((item) => ({
          variantId: item.variant_id.toString(),
          quantity: item.quantity,
          properties: item.properties,
        }))

        console.log('[qc] Opening checkout with', products.length, 'products')
        window.qcOpenCheckout({
          element: button || form,
          products,
          clearCartAfterComplete: true,
        })
      } catch (err) {
        console.error('[qc] Error:', err)

        if (button) {
          button.disabled = false
          button.textContent = button.dataset.originalText
        }

        // Fallback - let native form submit
        originalFormSubmit.call(form)
      }
    }
  }

  // listen to discount code updates
  // https://discountoncartpro.com/app-faq
  window.addEventListener('load', () => {
    document.body.addEventListener('docapp-discount-applied', (e) => {
      console.debug('docapp-discount-applied', e)
      console.debug('to pass discount:', {
        title: e.discounts[0].title,
        type: e.discounts[0].type,
      })
      if (e.discounts.length > 0) {
        setDiscount({ title: e.discounts[0].title, type: e.discounts[0].type })
      } else {
        resetDiscount()
      }
    })
  })
}
