/**
 * Auto Hover Color for Site Editor
 *
 * Subscribes to global styles changes. Auto-generates hover background color
 * using luminance-based logic when:
 * - User changes button background color directly
 * - User changes a palette color that the button references
 */
(function () {
  var subscribe = wp.data.subscribe;
  var select = wp.data.select;
  var dispatch = wp.data.dispatch;
  var config = window.brandyAutoHoverColor || {};

  // ── Color utilities ──────────────────────────────────────────────

  function hexToRGB(hex) {
    hex = hex.replace(/^#/, "");
    if (hex.length === 3) {
      hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
    }
    if (hex.length !== 6) return null;
    return {
      r: parseInt(hex.substring(0, 2), 16),
      g: parseInt(hex.substring(2, 4), 16),
      b: parseInt(hex.substring(4, 6), 16),
    };
  }

  function getLuminance(hex) {
    var rgb = hexToRGB(hex);
    if (!rgb) return 0;
    var r = rgb.r / 255;
    var g = rgb.g / 255;
    var b = rgb.b / 255;
    r = r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4);
    g = g <= 0.03928 ? g / 12.92 : Math.pow((g + 0.055) / 1.055, 2.4);
    b = b <= 0.03928 ? b / 12.92 : Math.pow((b + 0.055) / 1.055, 2.4);
    return 0.2126 * r + 0.7152 * g + 0.0722 * b;
  }

  function lightenColor(hex, amount) {
    var rgb = hexToRGB(hex);
    if (!rgb) return hex;
    var r = Math.min(255, Math.floor(rgb.r + (255 - rgb.r) * amount));
    var g = Math.min(255, Math.floor(rgb.g + (255 - rgb.g) * amount));
    var b = Math.min(255, Math.floor(rgb.b + (255 - rgb.b) * amount));
    return (
      "#" +
      [r, g, b]
        .map(function (x) {
          return x.toString(16).padStart(2, "0");
        })
        .join("")
    );
  }

  function darkenColor(hex, amount) {
    var rgb = hexToRGB(hex);
    if (!rgb) return hex;
    var r = Math.max(0, Math.floor(rgb.r * (1 - amount)));
    var g = Math.max(0, Math.floor(rgb.g * (1 - amount)));
    var b = Math.max(0, Math.floor(rgb.b * (1 - amount)));
    return (
      "#" +
      [r, g, b]
        .map(function (x) {
          return x.toString(16).padStart(2, "0");
        })
        .join("")
    );
  }

  function generateHoverColor(mainColor) {
    if (mainColor === "#000000") return "#2f2f2f";
    var luminance = getLuminance(mainColor);
    return luminance < 0.2
      ? lightenColor(mainColor, 0.1)
      : darkenColor(mainColor, 0.12);
  }

  // ── Preset resolution ──────────────────────────────────────────

  /**
   * Resolve preset color reference to hex.
   * Handles both formats:
   *   - Internal: var:preset|color|slug
   *   - CSS:      var(--wp--preset--color--slug)
   * Sources: 1) live entity settings  2) PHP initial palette
   */
  function resolvePreset(color, liveSettings) {
    if (!color || typeof color !== "string") return color;

    var slug = null;
    var match = color.match(/^var:preset\|color\|(.+)$/);
    if (match) {
      slug = match[1];
    } else {
      var cssMatch = color.match(/^var\(--wp--preset--color--(.+)\)$/);
      if (cssMatch) slug = cssMatch[1];
    }
    if (!slug) return color;

    // Source 1: live edited entity settings (unsaved palette changes)
    if (liveSettings && liveSettings.color && liveSettings.color.palette) {
      var palette = liveSettings.color.palette;
      var sources = ["custom", "theme", "default"];
      for (var s = 0; s < sources.length; s++) {
        var colors = palette[sources[s]];
        if (Array.isArray(colors)) {
          for (var j = 0; j < colors.length; j++) {
            if (colors[j].slug === slug) return colors[j].color;
          }
        }
      }
    }

    // Source 2: initial merged palette from PHP (page-load snapshot)
    var initialPalette = config.initialPalette || [];
    for (var i = 0; i < initialPalette.length; i++) {
      if (initialPalette[i].slug === slug) return initialPalette[i].color;
    }

    return color;
  }

  // ── Main subscription ────────────────────────────────────────────

  // Baseline from PHP: resolved hex of button bg at page load
  var lastResolvedBg = config.initialButtonBg || null;
  var isUpdating = false;

  var GLOBAL_STYLES_ID = config.globalStylesId
    ? parseInt(config.globalStylesId, 10)
    : null;

  function checkAndUpdateHoverColor() {
    if (isUpdating || !GLOBAL_STYLES_ID) return;

    var coreStore = select("core");
    if (!coreStore || !coreStore.getEditedEntityRecord) return;

    var entity = coreStore.getEditedEntityRecord(
      "root",
      "globalStyles",
      GLOBAL_STYLES_ID
    );

    if (!entity) return;

    const liveSettings = JSON.parse(JSON.stringify(entity.settings || {}));

    if ( !liveSettings?.color?.palette?.theme ) {
      liveSettings ??= {};
      liveSettings.color ??= {};
      liveSettings.color.palette ??= {};
      liveSettings.color.palette.theme ??= brandyAutoHoverColor.themePalette;
    }

    if ( !liveSettings?.color?.palette?.default ) {
      liveSettings ??= {};
      liveSettings.color ??= {};
      liveSettings.color.palette ??= {};
      liveSettings.color.palette.default ??= brandyAutoHoverColor.corePalette;
    }

    // Check if button bg exists in the edited entity (vs. theme default)
    var button =
      entity.styles &&
      entity.styles.elements &&
      entity.styles.elements.button;
    var entityHasBg = button && button.color && button.color.background;

    // If button bg was reset (removed from entity), also clear hover overrides
    // so theme.json defaults take over for both bg and hover
    if (!entityHasBg) {
      entityHasBg = window.brandyAutoHoverColor.defaultButtonBg;
    }
    
    var rawBg = entityHasBg;
    
    // Resolve preset to hex using live entity settings + PHP fallback
    var resolvedBg = resolvePreset(rawBg, liveSettings);
    // TODO: merge with default one
    if (!resolvedBg || resolvedBg.indexOf("var:") === 0) return;

    // No change since last check — skip
    if (resolvedBg === lastResolvedBg) return;
    lastResolvedBg = resolvedBg;

    // Generate and apply hover color
    var hoverColor = generateHoverColor(resolvedBg);

    var updatedStyles = JSON.parse(JSON.stringify(entity.styles || {}));
    if (!updatedStyles.elements) updatedStyles.elements = {};
    if (!updatedStyles.elements.button) updatedStyles.elements.button = {};
    if (!updatedStyles.elements.button[":hover"]) {
      updatedStyles.elements.button[":hover"] = {};
    }
    if (!updatedStyles.elements.button[":hover"].color) {
      updatedStyles.elements.button[":hover"].color = {};
    }
    updatedStyles.elements.button[":hover"].color.background = hoverColor;

    isUpdating = true;
    dispatch("core").editEntityRecord(
      "root",
      "globalStyles",
      GLOBAL_STYLES_ID,
      { styles: updatedStyles }
    );
    isUpdating = false;
  }

  wp.domReady(function () {
    if (!GLOBAL_STYLES_ID) return;
    subscribe(checkAndUpdateHoverColor);
  });
})();
