import "./custom-select.css";
import "./admin-product-swatches.css";
import { initLegacyCustomSelects } from "./custom-select";

jQuery(document).ready(function ($) {
  function closeAllPickersExcept($keepInput) {
    const $keep = $keepInput && $keepInput.length ? $keepInput : null;
    $("#b3wvs_swatches_panel")
      .find(".b3-wvs-color-picker")
      .each(function () {
        const $input = $(this);
        if ($keep && $input.is($keep)) return;
        if ($input.data("wpColorPicker")) {
          try {
            $input.wpColorPicker("close");
          } catch (e) {
            // ignore
          }
        }
      });
  }

  function initMetaboxToggles(context) {
    const $context = context ? $(context) : $(document);
    const $panel = $context.find("#b3wvs_swatches_panel");
    if (!$panel.length) return;

    // We use `.b3-wvs-handlediv` (not WordPress's `.handlediv`) to avoid triggering global
    // postbox toggle handlers. Intercept clicks and toggle only our local metabox.
    const panelEl = $panel.get(0);
    if (panelEl && !panelEl.__b3wvsHandledivCaptureBound) {
      panelEl.__b3wvsHandledivCaptureBound = true;
      panelEl.addEventListener(
        "click",
        function (event) {
          const target = event.target;
          if (!target || !target.closest) return;

          const handle = target.closest(".wc-metabox > h3 .b3-wvs-handlediv");
          if (!handle) return;
          if (!panelEl.contains(handle)) return;

          event.preventDefault();
          event.stopPropagation();

          const metabox = handle.closest(".wc-metabox");
          if (!metabox) return;

          const $box = $(metabox);
          const $content = $box.find("> .wc-metabox-content");
          const isOpen = $box.hasClass("open") && !$box.hasClass("closed");

          if (isOpen) {
            $box.removeClass("open").addClass("closed");
            $content.stop(true).slideUp(120);
          } else {
            $box.removeClass("closed");
            $content.stop(true).slideDown(120, function () {
              $box.addClass("open");
            });
          }
        },
        true,
      );
    }

    // Toggle per-attribute metabox open/closed.
    // Matches Woo's product data metabox behavior: clicking inputs in the header should not toggle.
    $panel.off("click.b3wvsMetabox");
    $panel.on("click.b3wvsMetabox", ".wc-metabox > h3", function (event) {
      if (
        $(event.target).filter(
          ":input, option, select, label, a, button, .b3-wvs-handlediv",
        ).length
      ) {
        return;
      }
      const $box = $(this).closest(".wc-metabox");
      const $content = $box.find("> .wc-metabox-content");
      const isOpen = $box.hasClass("open") && !$box.hasClass("closed");

      if (isOpen) {
        $box.removeClass("open").addClass("closed");
        $content.stop(true).slideUp(120);
      } else {
        $box.removeClass("closed");
        $content.stop(true).slideDown(120, function () {
          $box.addClass("open");
        });
      }
    });
  }

  function initColorPickers(context) {
    $(context)
      .find(".b3-wvs-color-picker")
      .each(function () {
        const $input = $(this);
        if ($input.data("wpColorPicker")) return;
        $input.wpColorPicker();
      });
  }

  function labelGlobalAttributeDropdowns(context) {
    const $context = context ? $(context) : $(document);
    const $selects = $context.find(
      '#attribute_taxonomy, select[name="attribute_taxonomy"], select[name^="attribute_taxonomy"]',
    );

    $selects.each(function () {
      const $select = $(this);
      $select.find("option").each(function () {
        const $option = $(this);
        const value = String($option.val() || "");
        if (!value || value === "none") return;
        if (!value.startsWith("pa_")) return;
        if ($option.data("b3WvsGlobalLabelApplied")) return;

        const text = String($option.text() || "").trim();
        if (!text.toLowerCase().includes("global")) {
          $option.text(`${text} (Global attribute)`);
        }
        $option.data("b3WvsGlobalLabelApplied", true);
      });
    });
  }

  function initSortableRows(context) {
    if (!$.fn.sortable) return;
    const $context = context ? $(context) : $(document);

    function normalizeToken(t) {
      return String(t || "").trim();
    }

    function splitAttributeValues(raw) {
      const s = String(raw || "");
      // Woo commonly uses " | " delimiter for custom attributes.
      // We'll be tolerant and split on pipe, then trim.
      return s
        .split("|")
        .map((v) => v.trim())
        .filter(Boolean);
    }

    function joinAttributeValues(values) {
      return (values || [])
        .map((v) => String(v))
        .filter(Boolean)
        .join(" | ");
    }

    function sanitizeLikeWp(value) {
      // Best-effort "sanitize_title" for matching.
      return String(value || "")
        .toLowerCase()
        .trim()
        .replace(/\s+/g, "-")
        .replace(/[^a-z0-9\-_]/g, "")
        .replace(/-+/g, "-");
    }

    function findWooAttributeRowByName(attributeName) {
      const $attrs = $("#product_attributes");
      if (!$attrs.length) return $();

      const wanted = normalizeToken(attributeName);
      const wantedSan = sanitizeLikeWp(wanted);

      let $match = $();
      $attrs.find(".woocommerce_attribute").each(function () {
        const $row = $(this);
        const $nameInput = $row.find('input[name^="attribute_names["]');
        if (!$nameInput.length) return;
        const current = normalizeToken($nameInput.val());
        if (!current) return;
        const currentSan = sanitizeLikeWp(current);

        if (current === wanted || currentSan === wantedSan) {
          $match = $row;
          return false;
        }
      });

      return $match;
    }

    function syncWooAttributesTextboxFromSwatches($swatchContainer) {
      if (!$swatchContainer || !$swatchContainer.length) return;

      const attributeName = $swatchContainer
        .closest(".wc-metabox")
        .data("attribute");
      if (!attributeName) return;

      // Collect current swatch order (exact tokens as rendered by PHP).
      const ordered = [];
      $swatchContainer.find("> .b3-wvs-row").each(function () {
        const slug = $(this).data("slug");
        const v = normalizeToken(slug);
        if (v) ordered.push(v);
      });
      if (!ordered.length) return;

      const $wooAttrRow = findWooAttributeRowByName(attributeName);
      if (!$wooAttrRow.length) return;

      // Prefer custom-attribute textarea (this is the "text input block" in Attributes).
      const $valuesTextarea = $wooAttrRow.find(
        'textarea[name^="attribute_values["]',
      );
      if ($valuesTextarea.length) {
        const existingRaw = String($valuesTextarea.val() || "");
        const existingTokens = splitAttributeValues(existingRaw);

        // Preserve exact existing token spelling when possible.
        const exactMap = new Map();
        existingTokens.forEach((t) => {
          exactMap.set(normalizeToken(t), t);
          exactMap.set(sanitizeLikeWp(t), t);
        });

        const finalTokens = [];
        const seen = new Set();
        ordered.forEach((t) => {
          const keyA = normalizeToken(t);
          const keyB = sanitizeLikeWp(t);
          const original = exactMap.get(keyA) || exactMap.get(keyB) || t;
          const outKey = normalizeToken(original);
          if (!outKey || seen.has(outKey)) return;
          finalTokens.push(original);
          seen.add(outKey);
        });

        // Append any existing values we didn't include (avoid accidental removal).
        existingTokens.forEach((t) => {
          const outKey = normalizeToken(t);
          if (!outKey || seen.has(outKey)) return;
          finalTokens.push(t);
          seen.add(outKey);
        });

        const nextRaw = joinAttributeValues(finalTokens);
        if (nextRaw !== existingRaw) {
          $valuesTextarea.val(nextRaw);
          $valuesTextarea.trigger("input");
          $valuesTextarea.trigger("change");
        }

        return;
      }

      // Taxonomy attributes: try to reorder selected options in a multi-select if present.
      const $multi = $wooAttrRow.find(
        'select[multiple][name^="attribute_values["]',
      );
      if ($multi.length) {
        const optionsByValue = new Map();
        $multi.find("option").each(function () {
          optionsByValue.set(String(this.value), this);
        });

        // ordered entries are slugs; Woo's select option values are often term IDs.
        // We can't safely map slug->ID without extra data, so skip in this fallback.
        // (Most "textbox reorder" workflows are custom attributes.)
        return;
      }
    }

    $context.find(".b3-wvs-attribute-metabox-content").each(function () {
      const $container = $(this);
      if ($container.data("b3wvsSortable")) return;
      $container.data("b3wvsSortable", true);
      $container.sortable({
        items: "> .b3-wvs-row",
        handle: ".b3-wvs-drag-handle",
        axis: "y",
        placeholder: "b3-wvs-row-placeholder",
        tolerance: "pointer",
        update: function () {
          // Live-sync into Woo's Attributes UI so Woo saves the new order naturally.
          syncWooAttributesTextboxFromSwatches($container);
        },
      });
    });
  }

  function initPickerOpenBehavior() {
    const panelEl = document.getElementById("b3wvs_swatches_panel");
    if (!panelEl || panelEl.__b3wvsPickerOpenBound) return;
    panelEl.__b3wvsPickerOpenBound = true;

    // 1) Never open picker when user clicks/focuses the hex input.
    // Use native capture so we beat any jQuery/WP bubble handlers.
    const blockOpenFromInput = function (event) {
      const target = event.target;
      if (!target) return;
      if (
        target.classList &&
        (target.classList.contains("wp-color-picker") ||
          target.classList.contains("b3-wvs-color-picker"))
      ) {
        event.stopPropagation();
      }
    };

    panelEl.addEventListener("click", blockOpenFromInput, true);
    panelEl.addEventListener("focus", blockOpenFromInput, true);

    // 2) Open picker ONLY when clicking the color chip.
    // Before opening, close all other pickers so only one is open.
    panelEl.addEventListener(
      "click",
      function (event) {
        const target = event.target;
        if (!target) return;

        const button = target.closest
          ? target.closest(".wp-color-result")
          : null;
        if (!button) return;

        const container = button.closest(".wp-picker-container");
        if (!container) return;
        if (!container.closest("#b3wvs_swatches_panel")) return;

        const $input = $(container).find(".b3-wvs-color-picker").first();
        closeAllPickersExcept($input);
        // Allow WP's default handler to actually open the picker.
      },
      true,
    );
  }

  function announcePanelReady(context) {
    const $context = context ? $(context) : $(panelSelector);
    $(document).trigger("b3wvs:productSwatchesPanelReady", [$context]);
  }

  function initSwatchTypeSelects(context) {
    initLegacyCustomSelects($, context, ".b3-wvs-swatch-type");
  }

  // Portal the color picker to body and position it with fixed positioning
  function portalPickerToBody($holder, $container) {
    // Skip if already portaled
    if ($holder.data("b3-portaled")) return;

    const $button = $container.find(".wp-color-result");
    if (!$button.length) return;

    // Mark as portaled
    $holder.data("b3-portaled", true);

    // Store original parent for potential cleanup
    $holder.data("b3-original-parent", $holder.parent());

    // Move to body
    $holder.appendTo("body");

    // Position based on button location
    const buttonRect = $button[0].getBoundingClientRect();
    const pickerHeight = $holder.outerHeight() || 200;
    const pickerWidth = $holder.outerWidth() || 260;
    const viewportHeight = window.innerHeight;
    const viewportWidth = window.innerWidth;
    const spacing = 8;

    let top, left;

    // Try to position above the button first
    if (buttonRect.top > pickerHeight + spacing) {
      top = buttonRect.top - pickerHeight - spacing + window.scrollY;
    } else {
      // Position below if not enough space above
      top = buttonRect.bottom + spacing + window.scrollY;
    }

    // Align left edge with button, but keep within viewport
    left = buttonRect.left + window.scrollX;
    if (left + pickerWidth > viewportWidth - 10) {
      left = viewportWidth - pickerWidth - 10;
    }
    if (left < 10) {
      left = 10;
    }

    $holder.css({
      position: "absolute",
      top: top + "px",
      left: left + "px",
      bottom: "auto",
      right: "auto",
      zIndex: 100100,
    });
  }

  // Return picker to original location when closed
  function returnPickerFromBody($holder) {
    if (!$holder.data("b3-portaled")) return;

    const $originalParent = $holder.data("b3-original-parent");
    if ($originalParent && $originalParent.length) {
      $holder.appendTo($originalParent);
    }

    $holder.css({
      position: "",
      top: "",
      left: "",
      bottom: "",
      right: "",
      zIndex: "",
    });

    $holder.removeData("b3-portaled");
    $holder.removeData("b3-original-parent");
  }

  // Monitor for color picker popups and add close buttons
  const observeColorPickers = function () {
    const observer = new MutationObserver(function (mutations) {
      mutations.forEach(function (mutation) {
        if (
          mutation.type === "attributes" &&
          mutation.attributeName === "style"
        ) {
          const $holder = $(mutation.target);
          const $container = $holder.closest(".wp-picker-container");

          // Handle picker in body (portaled)
          if ($holder.data("b3-portaled")) {
            if (!$holder.is(":visible")) {
              returnPickerFromBody($holder);
            }
            return;
          }

          if ($holder.hasClass("wp-picker-holder") && $holder.is(":visible")) {
            if ($container.closest("#b3wvs_swatches_panel").length) {
              // Portal the picker to body
              portalPickerToBody($holder, $container);

              if (!$holder.find(".b3-wvs-picker-close").length) {
                const $input = $container.find(".b3-wvs-color-picker");

                // Enforce single-open picker even if WP tries to open another.
                closeAllPickersExcept($input);

                const $closeBtn = $(
                  '<button type="button" class="b3-wvs-picker-close" aria-label="Close color picker">&times;</button>',
                );
                $closeBtn.on("click", function (e) {
                  e.preventDefault();
                  e.stopPropagation();
                  if ($input.data("wpColorPicker")) {
                    $input.wpColorPicker("close");
                  }
                });
                $holder.prepend($closeBtn);
              }
            }
          }
        }
      });
    });

    // Observe all wp-picker-holder elements in the panel
    $("#b3wvs_swatches_panel")
      .find(".wp-picker-holder")
      .each(function () {
        observer.observe(this, {
          attributes: true,
          attributeFilter: ["style"],
        });
      });
  };

  // Initialize observer when panel is ready
  const $panelInit = $("#b3wvs_swatches_panel");
  if ($panelInit.length) {
    observeColorPickers();
    initPickerOpenBehavior();
    initSortableRows($panelInit);
    initSwatchTypeSelects($panelInit);
    announcePanelReady($panelInit);
  }

  // Re-initialize when tab is clicked
  $(document).on("click", ".b3wvs_swatches_options a", function () {
    setTimeout(observeColorPickers, 100);
    setTimeout(function () {
      const $panel = $("#b3wvs_swatches_panel");
      initSortableRows($panel);
      labelGlobalAttributeDropdowns($panel);
      initSwatchTypeSelects($panel);
      announcePanelReady($panel);
    }, 120);
  });

  labelGlobalAttributeDropdowns($(document));

  $(document).on(
    "click",
    ".attribute_tab a, .wc-tabs .attributes_tab a",
    function () {
      setTimeout(function () {
        labelGlobalAttributeDropdowns($("#product_attributes"));
      }, 120);
    },
  );

  // Close color pickers when clicking/tapping outside
  // Use mousedown only (not touchstart) to avoid passive event listener warning
  $(document).on("mousedown", function (e) {
    if (!$(e.target).closest(".wp-picker-container").length) {
      $(".b3-wvs-color-picker").each(function () {
        const $this = $(this);
        if ($this.data("wpColorPicker")) {
          $this.wpColorPicker("close");
        }
      });
    }
  });

  function toggleRow($row) {
    const type = $row.find(".b3-wvs-swatch-type").val();
    const normalizedType = String(type || "");
    const extensionBridge =
      window.b3WvsProductSwatchesExtension &&
      typeof window.b3WvsProductSwatchesExtension.toggleRow === "function"
        ? window.b3WvsProductSwatchesExtension
        : null;
    const $fieldsContainer = $row.find(".b3-wvs-col-fields");
    const $labelCol = $fieldsContainer.find(".b3-wvs-col-label");
    const $colorCol = $fieldsContainer.find(".b3-wvs-col-color");
    const $colorLabel = $colorCol.find("> label").first();
    const $useColor = $row.find(".b3-wvs-use-color");
    const $toggleBtn = $row.find(".b3-wvs-toggle-color");

    const $labelInput = $labelCol.find('input[type="text"][name*="[label]"]');
    const $labelLabel = $labelCol.find("> label").first();
    // Update type class for CSS visibility rules
    $row.removeClass(
      "type-default type-button type-color type-dual-color type-image type-number color-enabled",
    );
    if (normalizedType === "button") {
      $row.addClass("type-button");
    } else if (normalizedType === "color") {
      $row.addClass("type-color");
    } else {
      $row.addClass("type-default");
    }

    const clearColorInputs = ($inputs) => {
      $inputs.each(function () {
        const $input = $(this);
        $input.val("");
        if ($input.data("wpColorPicker")) {
          try {
            $input.wpColorPicker("color", "");
          } catch (e) {
            // ignore
          }
        }
        $input.trigger("change");
      });
    };

    const clearPrimaryColor = () => {
      clearColorInputs($row.find(".b3-wvs-color-picker-primary"));
    };

    const clearSecondaryColor = () => {
      clearColorInputs($row.find(".b3-wvs-color-picker-secondary"));
    };

    const clearAllColors = () => {
      clearColorInputs($row.find(".b3-wvs-color-picker"));
    };

    const setUseColor = (enabled) => {
      if (!$useColor.length) return;
      $useColor.prop("checked", Boolean(enabled));
      const isEnabled = $useColor.prop("checked");
      if ($toggleBtn.length) {
        $toggleBtn.text(isEnabled ? "Remove color" : "Add color");
        $toggleBtn.attr("aria-expanded", isEnabled ? "true" : "false");
      }
    };

    const isUseColorEnabled = () => {
      if (!$useColor.length) return false;
      return Boolean($useColor.prop("checked"));
    };

    const syncColorLabel = () => {
      if (!$colorLabel.length) {
        return;
      }

      const defaultLabel = String($colorCol.data("labelDefault") || "Color");
      const buttonLabel = String($colorCol.data("labelButton") || defaultLabel);
      $colorLabel.text(
        normalizedType === "button" ? buttonLabel : defaultLabel,
      );
    };

    syncColorLabel();

    // Ensure optional color state survives initial load even if older data has colors but no use_color.
    // IMPORTANT: this must not re-enable color after the user explicitly clicked "Remove color".
    if (
      normalizedType === "button" &&
      $useColor.length &&
      !$row.data("b3wvsUseColorInferred")
    ) {
      const hasAnyColor = Boolean(
        String($row.find(".b3-wvs-color-picker-primary").val() || "").trim(),
      );
      if (!isUseColorEnabled() && hasAnyColor) {
        setUseColor(true);
      }
      $row.data("b3wvsUseColorInferred", true);
    }

    // Show relevant columns based on type
    if (normalizedType === "") {
      // Default: show only the Type selector.
      clearAllColors();
      if ($useColor.length) setUseColor(false);

      // Clear hidden fields so switching back to Default doesn't carry stale data.
      if ($labelInput.length) {
        $labelInput.val("").trigger("change");
      }
      return;
    }

    if (normalizedType === "button") {
      // Button can optionally have a primary color via the toggle.
      // Button shows Label Text + Add/Remove color. No "Hide Text".
      if ($labelLabel.length) $labelLabel.show();
      if ($labelInput.length) $labelInput.show();

      const enabled = isUseColorEnabled();
      // Keep toggle UI (text/aria) in sync with current state.
      setUseColor(enabled);
      if (enabled) {
        $row.addClass("color-enabled");
        clearSecondaryColor();
      } else {
        // Keep data clean when color is not enabled.
        clearAllColors();
      }
      return;
    }

    if (normalizedType === "color") {
      if ($useColor.length) setUseColor(false);
      clearSecondaryColor();
      if ($useColor.length) setUseColor(false);
      return;
    }

    if (
      extensionBridge &&
      extensionBridge.toggleRow({
        $row,
        type: normalizedType,
        clearSecondaryColor,
        clearAllColors,
        setUseColor,
        isUseColorEnabled,
        $labelInput,
        $labelLabel,
      })
    ) {
      return;
    }

    // Preserve extension/unknown values until the extension bridge can apply
    // the correct row-state contract. Clearing here wipes saved Pro values on
    // initial bootstrap before the extension script runs.
    return;
  }

  const panelSelector = "#b3wvs_swatches_panel";
  const $panel = $(panelSelector);

  const hasEyeDropper = typeof window.EyeDropper === "function";

  if ($panel.length) {
    initMetaboxToggles($panel);
    initColorPickers($panel);
    initSortableRows($panel);
    initSwatchTypeSelects($panel);
    $panel.find(".b3-wvs-row").each(function () {
      toggleRow($(this));
    });

    if (!hasEyeDropper) {
      $panel.find(".b3-wvs-eyedropper").hide();
    }

    announcePanelReady($panel);
  }

  // Also initialize when the tab is clicked (WooCommerce tabs)
  $(document).on("click", ".b3wvs_swatches_options a", function () {
    setTimeout(function () {
      const $p = $(panelSelector);
      if ($p.length) {
        initMetaboxToggles($p);
        initColorPickers($p);
        initSwatchTypeSelects($p);
        $p.find(".b3-wvs-row").each(function () {
          toggleRow($(this));
        });
        announcePanelReady($p);
      }
    }, 100);
  });

  $(document).on("change", panelSelector + " .b3-wvs-swatch-type", function () {
    toggleRow($(this).closest(".b3-wvs-row"));
  });

  // Button/Label: toggle optional color UI
  $(document).on(
    "click",
    panelSelector + " .b3-wvs-toggle-color",
    function (e) {
      e.preventDefault();
      const $row = $(this).closest(".b3-wvs-row");
      const type = $row.find(".b3-wvs-swatch-type").val();
      if (String(type) !== "button") return;

      const $useColor = $row.find(".b3-wvs-use-color");
      if (!$useColor.length) return;

      const enabled = Boolean($useColor.prop("checked"));
      $useColor.prop("checked", !enabled);
      toggleRow($row);
    },
  );

  // Variations panel HTML can be re-rendered by Woo; re-init color pickers when tabs change.
  $(document).on(
    "woocommerce_variations_loaded woocommerce_variations_added",
    function () {
      const $p = $(panelSelector);
      initMetaboxToggles($p);
      initColorPickers($p);
      initSwatchTypeSelects($p);
      $p.find(".b3-wvs-row").each(function () {
        toggleRow($(this));
      });
    },
  );

  // ---------------------------------------------------------------------------
  // Auto-refresh Swatches panel when WooCommerce attributes are saved
  // ---------------------------------------------------------------------------

  /**
   * Refresh the swatches panel via AJAX when attributes are saved.
   * This ensures newly added attributes appear without a page reload.
   */
  function refreshSwatchesPanel() {
    const $panel = $(panelSelector);
    if (!$panel.length) return;

    const data = window.b3WvsData || {};
    const ajaxUrl = data.ajax_url || window.ajaxurl;
    const nonce = data.refresh_panel_nonce;

    // Get the post ID from the form or URL
    let postId = 0;
    const $postIdInput = $('input#post_ID, input[name="post_ID"]');
    if ($postIdInput.length) {
      postId = parseInt($postIdInput.val(), 10);
    }
    if (!postId) {
      // Try to get from URL
      const urlParams = new URLSearchParams(window.location.search);
      postId = parseInt(urlParams.get("post"), 10);
    }

    if (!postId || !nonce) {
      // Fallback: reload the page if we can't do AJAX refresh
      window.location.reload();
      return;
    }

    // Show loading state
    $panel.addClass("b3-wvs-panel-loading");
    $panel.find(".wc-metaboxes").first().css("opacity", "0.5");

    $.ajax({
      url: ajaxUrl,
      type: "POST",
      data: {
        action: "b3wvs_refresh_swatches_panel",
        nonce: nonce,
        post_id: postId,
      },
      success: function (response) {
        if (
          response &&
          response.success &&
          response.data &&
          response.data.html
        ) {
          // Replace the panel content
          const $newPanel = $(response.data.html);
          $panel.replaceWith($newPanel);

          // Re-initialize all UI components on the new panel
          const $refreshedPanel = $(panelSelector);
          initMetaboxToggles($refreshedPanel);
          initColorPickers($refreshedPanel);
          initSortableRows($refreshedPanel);
          initSwatchTypeSelects($refreshedPanel);
          observeColorPickers();
          $refreshedPanel.find(".b3-wvs-row").each(function () {
            toggleRow($(this));
          });

          // Re-initialize picker open behavior
          initPickerOpenBehavior();

          if (!hasEyeDropper) {
            $refreshedPanel.find(".b3-wvs-eyedropper").hide();
          }

          announcePanelReady($refreshedPanel);
        } else {
          // If AJAX fails, fall back to page reload
          window.location.reload();
        }
      },
      error: function () {
        // On error, fall back to page reload
        window.location.reload();
      },
    });
  }

  // Listen for WooCommerce attribute save event
  $(document.body).on("woocommerce_attributes_saved", function () {
    // Small delay to ensure WooCommerce has finished processing
    setTimeout(refreshSwatchesPanel, 300);
  });

  // EyeDropper support (Chrome/Edge). Gracefully hide when unsupported.
  $(document).on("click", panelSelector + " .b3-wvs-eyedropper", function (e) {
    e.preventDefault();
    if (!hasEyeDropper) return;
    const $button = $(this);
    const $row = $button.closest(".b3-wvs-row");
    const target = String($button.data("target") || "primary");
    const $input =
      target === "secondary"
        ? $row.find(".b3-wvs-color-picker-secondary")
        : $row.find(".b3-wvs-color-picker-primary");

    const picker = new window.EyeDropper();
    picker
      .open()
      .then((result) => {
        if (!result || !result.sRGBHex) return;
        const hex = result.sRGBHex;
        $input.val(hex);
        if ($input.data("wpColorPicker")) {
          $input.wpColorPicker("color", hex);
          // Don't auto-close - let user continue picking if needed
        } else {
          $input.trigger("change");
        }
      })
      .catch((err) => {
        // Abort is expected when user cancels; ignore other errors silently.
        if (err && err.name !== "AbortError") {
          // noop
        }
      });
  });
});
