/**
 * Brandy Responsive Conditions — WP 7.0+ bridge helpers.
 *
 * Loaded BEFORE script.js (as a script dep). Exposes a single global
 * `BrandyResponsiveConditionsHelpers` consumed by the editor extension.
 *
 * See: plans/260518-1152-wp7-block-visibility-bridge/phase-01-spike-findings.md
 *
 * WP 7.0 stores per-viewport visibility at
 *   attrs.metadata.blockVisibility.viewport.{slug}
 * with value `false` meaning "hidden on this viewport". Absent or `true` =
 * visible. Brandy's legacy attrs (hideOn{Device}) coexist via OR-combined
 * pressed state.
 */
(function (global) {
  const IS_WP7_PLUS = !!(
    global.BrandyResponsiveConditions && global.BrandyResponsiveConditions.isWp7Plus
  );
  const HIDDEN_VALUE = false;
  const DEVICE_TO_VIEWPORT_KEY = {
    hideOnDesktop: "desktop",
    hideOnTablet: "tablet",
    hideOnMobile: "mobile",
  };

  /**
   * True if `deviceKey` is hidden via legacy attr OR (on WP 7.0+) via native
   * blockVisibility.viewport. Drives toolbar pressed state and editor outline.
   */
  function isHiddenForDevice(attributes, deviceKey) {
    if (attributes[deviceKey]) return true;
    if (!IS_WP7_PLUS) return false;
    // Scalar `metadata.blockVisibility === false` means "hidden everywhere"
    // per WP 7.0 core (wp-includes/block-supports/block-visibility.php:29-31).
    // Treat all devices as hidden so the toolbar pressed state matches reality.
    if (attributes.metadata && attributes.metadata.blockVisibility === false) return true;
    const viewportKey = DEVICE_TO_VIEWPORT_KEY[deviceKey];
    return (
      attributes.metadata &&
      attributes.metadata.blockVisibility &&
      attributes.metadata.blockVisibility.viewport &&
      attributes.metadata.blockVisibility.viewport[viewportKey] === HIDDEN_VALUE
    );
  }

  /**
   * Toggle hidden state for `deviceKey`. Always writes the legacy `hideOn*`
   * attr. On WP 7.0+, additionally writes
   * attrs.metadata.blockVisibility.viewport.{slug}. Cleans up empty viewport /
   * blockVisibility / metadata containers to keep post_content tidy. Preserves
   * any existing scalar blockVisibility (BC).
   */
  function toggleHidden(setAttributes, attributes, deviceKey, nextHidden) {
    const patch = { [deviceKey]: nextHidden };

    if (IS_WP7_PLUS) {
      const viewportKey = DEVICE_TO_VIEWPORT_KEY[deviceKey];
      const existingMetadata = attributes.metadata || {};
      const existingBV = existingMetadata.blockVisibility;

      // Don't clobber a scalar `false` (BC: WP 7.0 treats it as "hide everywhere").
      if (existingBV === false) {
        setAttributes(patch);
        return;
      }

      const existingViewport =
        (existingBV && typeof existingBV === "object" && existingBV.viewport) || {};
      const nextViewport = { ...existingViewport };
      if (nextHidden) {
        nextViewport[viewportKey] = HIDDEN_VALUE;
      } else {
        delete nextViewport[viewportKey];
      }

      let nextBV;
      if (Object.keys(nextViewport).length > 0) {
        nextBV = {
          ...(typeof existingBV === "object" ? existingBV : {}),
          viewport: nextViewport,
        };
      } else {
        // viewport empty — drop blockVisibility entirely if it has no other keys.
        const rest = typeof existingBV === "object" ? { ...existingBV } : {};
        delete rest.viewport;
        nextBV = Object.keys(rest).length > 0 ? rest : undefined;
      }

      const nextMetadata = { ...existingMetadata };
      if (nextBV === undefined) {
        delete nextMetadata.blockVisibility;
      } else {
        nextMetadata.blockVisibility = nextBV;
      }
      patch.metadata = Object.keys(nextMetadata).length > 0 ? nextMetadata : undefined;
    }

    setAttributes(patch);
  }

  global.BrandyResponsiveConditionsHelpers = {
    IS_WP7_PLUS,
    HIDDEN_VALUE,
    DEVICE_TO_VIEWPORT_KEY,
    isHiddenForDevice,
    toggleHidden,
  };
})(window);
