/**
 * HoverSettings - Block editor hover controls
 *
 * Adds hover text color, hover background color, and hover border
 * controls to blocks that support those features.
 *
 * Single file by design: no module system available (plain JS, no build step).
 * Splitting would require global namespace coordination and extra HTTP requests.
 */
(function () {
  var el = wp.element.createElement;
  var Fragment = wp.element.Fragment;
  var useEffect = wp.element.useEffect;
  var useRef = wp.element.useRef;
  var useMemo = wp.element.useMemo;
  var __ = wp.i18n.__;
  var addFilter = wp.hooks.addFilter;
  var createHigherOrderComponent = wp.compose.createHigherOrderComponent;
  var InspectorControls = wp.blockEditor.InspectorControls;
  var ColorGradientSettingsDropdown =
    wp.blockEditor.__experimentalColorGradientSettingsDropdown;
  var useMultipleOriginColorsAndGradients =
    wp.blockEditor.__experimentalUseMultipleOriginColorsAndGradients;
  var ToolsPanelItem = wp.components.__experimentalToolsPanelItem;
  var BorderBoxControl = wp.components.__experimentalBorderBoxControl;

  // ── Block support detection ───────────────────────────────────────

  function isBlockSupportBackgroundColor(blockName) {
    var support = wp.blocks.getBlockSupport(blockName, "color");
    return (
      (support && support.background) ||
      (support &&
        support.__experimentalDefaultControls &&
        support.__experimentalDefaultControls.background)
    );
  }

  function isBlockSupportTextColor(blockName) {
    var support = wp.blocks.getBlockSupport(blockName, "color");
    return (
      (support && support.text) ||
      (support &&
        support.__experimentalDefaultControls &&
        support.__experimentalDefaultControls.text)
    );
  }

  function isBlockSupportBorder(blockName) {
    return wp.blocks.hasBlockSupport(blockName, "__experimentalBorder");
  }

  // ── Color utility functions ───────────────────────────────────────

  function hexToRgb(hex) {
    var result6 = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    var result8 =
      /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);

    if (result8) {
      return {
        r: parseInt(result8[1], 16),
        g: parseInt(result8[2], 16),
        b: parseInt(result8[3], 16),
        a: parseInt(result8[4], 16) / 255,
      };
    }
    if (result6) {
      return {
        r: parseInt(result6[1], 16),
        g: parseInt(result6[2], 16),
        b: parseInt(result6[3], 16),
      };
    }
    return null;
  }

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

  function darkenColor(hex, amount) {
    if (amount === undefined) amount = 0.15;
    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)));
    var parts = [r, g, b].map(function (x) {
      return x.toString(16).padStart(2, "0");
    });
    if (rgb.a !== undefined) {
      parts.push(Math.round(rgb.a * 255).toString(16).padStart(2, "0"));
    }
    return "#" + parts.join("");
  }

  function lightenColor(hex, amount) {
    if (amount === undefined) amount = 0.15;
    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));
    var parts = [r, g, b].map(function (x) {
      return x.toString(16).padStart(2, "0");
    });
    if (rgb.a !== undefined) {
      parts.push(Math.round(rgb.a * 255).toString(16).padStart(2, "0"));
    }
    return "#" + parts.join("");
  }

  function getOptimalTextColor(bgColor) {
    return getLuminance(bgColor) > 0.5 ? "#000000" : "#ffffff";
  }

  function generateButtonColors(mainColor) {
    var luminance = getLuminance(mainColor);
    var hoverColor =
      mainColor === "#000000"
        ? "#2f2f2f"
        : luminance < 0.2
        ? lightenColor(mainColor, 0.1)
        : darkenColor(mainColor, 0.12);
    return {
      mainColor: mainColor,
      hoverColor: hoverColor,
      textColor: getOptimalTextColor(mainColor),
      textHoverColor: getOptimalTextColor(hoverColor),
    };
  }

  function getColorFromPalette(color, palette) {
    if (!palette) palette = [];
    var found = palette.find(function (c) {
      return c.slug === color;
    });
    return found ? found.color : color;
  }

  // ── Border hover style helper ─────────────────────────────────────

  function getBorderHoverStyleFromAttributes(attributes, props) {
    var style = {};
    var blockName = props.block && props.block.name;

    if (
      ["core/group", "core/columns"].indexOf(blockName) !== -1 &&
      attributes.style &&
      attributes.style.border &&
      attributes.style.border.radius
    ) {
      style["overflow"] = "hidden";
    }

    var hoverBorder =
      attributes.style && attributes.style.hoverBorder
        ? attributes.style.hoverBorder
        : {};

    if (Object.keys(hoverBorder).length > 0) {
      if (Object.keys(hoverBorder).indexOf("top") !== -1) {
        ["top", "bottom", "left", "right"].forEach(function (aspect) {
          if (hoverBorder[aspect]) {
            style["--hover-border-" + aspect + "-c"] =
              hoverBorder[aspect].color;
            style["--hover-border-" + aspect + "-w"] =
              hoverBorder[aspect].width;
            style["--hover-border-" + aspect + "-s"] =
              hoverBorder[aspect].style;
          }
        });
      } else {
        if (hoverBorder.color !== undefined) style["--hover-border-c"] = hoverBorder.color;
        if (hoverBorder.width !== undefined) style["--hover-border-w"] = hoverBorder.width;
        if (hoverBorder.style !== undefined) style["--hover-border-s"] = hoverBorder.style;
      }
    }

    return style;
  }

  // ── Settings panel component ──────────────────────────────────────

  function HoverSettingsPanel(props) {
    var isFirstRender = useRef(true);
    var colorGradientSettings = useMultipleOriginColorsAndGradients();
    var attributes = props.attributes;
    var setAttributes = props.setAttributes;
    var blockName = props.name;
    var clientId = props.clientId;

    var hoverBackgroundColor =
      (attributes.style && attributes.style.hoverBackgroundColor) || "";
    var hoverTextColor =
      (attributes.style && attributes.style.hoverTextColor) || "";
    var hoverBorder =
      (attributes.style && attributes.style.hoverBorder) || {};
    var hasHoverTextColor = isBlockSupportTextColor(blockName) || false;
    var hasHoverBackgroundColor =
      isBlockSupportBackgroundColor(blockName) || false;
    var hasHoverBorder = isBlockSupportBorder(blockName) || false;

    // Auto-generate hover color for button blocks
    var isOutline = (attributes.className || "").indexOf("is-style-outline") !== -1;
    var isGhost = (attributes.className || "").indexOf("is-style-ghost") !== -1;
    var isSecondary = (attributes.className || "").indexOf("is-style-secondary") !== -1;
    var isButtonBlock = ["core/button", "woocommerce/product-button", "brandy/button"].indexOf(blockName) !== -1;

    // Detect current button style variant
    var currentStyle = isOutline ? "outline" : isGhost ? "ghost" : isSecondary ? "secondary" : "fill";
    var prevStyleRef = useRef(currentStyle);

    // Reset all per-block color/hover/border settings when switching button style
    useEffect(
      function () {
        if (!isButtonBlock) return;
        if (prevStyleRef.current === currentStyle) return;
        prevStyleRef.current = currentStyle;

        console.log(currentStyle)

        setTimeout(()=>{
          setAttributes({
            style: Object.assign({}, attributes.style || {}, {
              color: undefined,
              border: undefined,
              hoverBackgroundColor: undefined,
              hoverTextColor: undefined,
              hoverBorder: undefined,
            }),
            backgroundColor: undefined,
            textColor: undefined,
            borderColor: undefined,
          });
        },0)
      },
      [currentStyle, isButtonBlock]
    );

    // Resolve the trigger color (the color that drives hover generation)
    // Memoized so useEffect only fires when the actual resolved hex changes
    var resolvedTriggerColor = useMemo(function () {
      if (!isButtonBlock) return "";
      var palette = (colorGradientSettings.colors || []).reduce(function (acc, p) {
        return acc.concat(p.colors || []);
      }, []);

      if (isOutline) {
        // Outline: only text color drives hover generation (border is independent)
        var outlineColor = attributes.textColor
          || (attributes.style && attributes.style.color && attributes.style.color.text)
          || "";
        return getColorFromPalette(outlineColor, palette) || "";
      }
      if (isGhost) {
        // Ghost: text color drives hover background
        var ghostColor = attributes.textColor
          || (attributes.style && attributes.style.color && attributes.style.color.text)
          || "";
        return getColorFromPalette(ghostColor, palette) || "";
      }
      // Fill + Secondary: background color
      var bgColor = attributes.backgroundColor
        || (attributes.style && attributes.style.color && attributes.style.color.background)
        || "";
      return getColorFromPalette(bgColor, palette) || "";
    }, [
      isButtonBlock, isOutline, isGhost, isSecondary,
      attributes.borderColor, attributes.textColor, attributes.backgroundColor,
      attributes.style && attributes.style.border && attributes.style.border.color,
      attributes.style && attributes.style.color && attributes.style.color.text,
      attributes.style && attributes.style.color && attributes.style.color.background,
      colorGradientSettings.colors,
    ]);

    // Fill button: auto-generate darkened hover background
    useEffect(
      function () {
        if (!isButtonBlock || isOutline || isGhost || isSecondary) return;
        if (isFirstRender.current) {
          isFirstRender.current = false;
          return;
        }
        var generated = generateButtonColors(resolvedTriggerColor);
        var hoverColor = generated && generated.hoverColor ? generated.hoverColor : "";
        var updatedStyle = Object.assign({}, attributes.style || {}, {
          hoverBackgroundColor: hoverColor,
          hoverTextColor: undefined,
          hoverBorder: undefined,
        });
        // Clear text color and border color so they fall to global/theme defaults
        updatedStyle.color = Object.assign({}, updatedStyle.color || {}, {
          text: undefined,
        });
        if (updatedStyle.border) {
          updatedStyle.border = Object.assign({}, updatedStyle.border, {
            color: undefined,
            style: undefined,
            width: undefined,
          });
        }
        setAttributes({ style: updatedStyle, borderColor: undefined });
      },
      [resolvedTriggerColor, isButtonBlock, isOutline, isGhost, isSecondary]
    );

    // Outline button: auto-generate hover bg, border, and text color
    useEffect(
      function () {
        if (!isButtonBlock || !isOutline) return;
        if (isFirstRender.current) {
          isFirstRender.current = false;
          return;
        }
        var outlineHoverStyle =
          window.brandyHoverSettings && window.brandyHoverSettings.outlineHoverStyle
            ? window.brandyHoverSettings.outlineHoverStyle
            : "solid";

        var updatedStyle = Object.assign({}, attributes.style || {});

        if (resolvedTriggerColor) {
          // Hover background: tinted = 10% opacity, solid = full color
          updatedStyle.hoverBackgroundColor = outlineHoverStyle === "tinted"
            ? "#" + resolvedTriggerColor.replace(/^#/, "").substring(0, 6) + "1a"
            : resolvedTriggerColor;
          // Sync text color, clear background (outline = transparent)
          updatedStyle.color = Object.assign({}, updatedStyle.color || {}, {
            text: resolvedTriggerColor,
            background: undefined
          });
          // Sync border color to match text color (clears custom border override)
          updatedStyle.border = Object.assign({}, updatedStyle.border || {}, {
            color: resolvedTriggerColor,
          });
          // Hover border matches outline color
          updatedStyle.hoverBorder = { color: resolvedTriggerColor };
          // Hover text: tinted keeps text color, solid uses contrast-aware color
          updatedStyle.hoverTextColor = outlineHoverStyle === "tinted"
            ? resolvedTriggerColor
            : getOptimalTextColor(resolvedTriggerColor);
        } else {
          // Colors reset: clear auto-generated hover values
          updatedStyle.hoverBackgroundColor = "";
          updatedStyle.hoverBorder = undefined;
          updatedStyle.hoverTextColor = undefined;
          updatedStyle.border = Object.assign({}, updatedStyle.border || {}, {
            color: undefined,
          });
        }

        setAttributes({ style: updatedStyle, borderColor: undefined });
      },
      [resolvedTriggerColor, isButtonBlock, isOutline]
    );

    // Ghost button: auto-generate light hover background from text color
    useEffect(
      function () {
        if (!isButtonBlock || !isGhost) return;
        if (isFirstRender.current) {
          isFirstRender.current = false;
          return;
        }

        var updatedStyle = Object.assign({}, attributes.style || {});

        if (resolvedTriggerColor) {
          // Hover background = light tint of text color (~92% toward white)
          updatedStyle.hoverBackgroundColor = lightenColor(resolvedTriggerColor, 0.92);
        } else {
          updatedStyle.hoverBackgroundColor = "";
        }

        // Clear: background, hover text, border, hover border
        updatedStyle.color = Object.assign({}, updatedStyle.color || {}, {
          background: undefined,
        });
        updatedStyle.hoverTextColor = undefined;
        updatedStyle.hoverBorder = undefined;
        if (updatedStyle.border) {
          updatedStyle.border = Object.assign({}, updatedStyle.border, {
            color: undefined,
          });
        }

        setAttributes({ style: updatedStyle });
      },
      [resolvedTriggerColor, isButtonBlock, isGhost]
    );

    // Secondary button: auto-generate slightly lighter hover background from bg
    useEffect(
      function () {
        if (!isButtonBlock || !isSecondary) return;
        if (isFirstRender.current) {
          isFirstRender.current = false;
          return;
        }

        var updatedStyle = Object.assign({}, attributes.style || {});

        if (resolvedTriggerColor) {
          // Hover background = slightly lighter version (~11% toward white)
          updatedStyle.hoverBackgroundColor = lightenColor(resolvedTriggerColor, 0.11);
        } else {
          updatedStyle.hoverBackgroundColor = "";
        }

        setAttributes({ style: updatedStyle });
      },
      [resolvedTriggerColor, isButtonBlock, isSecondary]
    );

    var children = [];

    // Color controls (hover text + hover background)
    if (hasHoverTextColor || hasHoverBackgroundColor) {
      var colorChildren = [];

      if (hasHoverTextColor) {
        colorChildren.push(
          el(
            ColorGradientSettingsDropdown,
            Object.assign(
              {
                key: "hover-text-color",
                settings: [
                  {
                    label: __("Hover color", "brandy"),
                    colorValue: hoverTextColor,
                    clearable: true,
                    enableAlpha: true,
                    onColorChange: function (value) {
                      setAttributes({
                        style: Object.assign({}, attributes.style || {}, {
                          hoverTextColor: value,
                        }),
                      });
                    },
                    resetAllFilter: function (prev) {
                      prev.style.hoverTextColor = undefined;
                      return prev;
                    },
                  },
                ],
                panelId: clientId,
                hasColorsOrGradients: false,
                disableCustomColors: false,
                __experimentalIsRenderedInSidebar: true,
              },
              colorGradientSettings
            )
          )
        );
      }

      if (hasHoverBackgroundColor) {
        colorChildren.push(
          el(
            ColorGradientSettingsDropdown,
            Object.assign(
              {
                key: "hover-bg-color",
                settings: [
                  {
                    label: __("Hover background color", "brandy"),
                    colorValue: hoverBackgroundColor,
                    clearable: true,
                    enableAlpha: true,
                    onColorChange: function (value) {
                      setAttributes({
                        style: Object.assign({}, attributes.style || {}, {
                          hoverBackgroundColor: value,
                        }),
                      });
                    },
                    resetAllFilter: function (prev) {
                      prev.style.hoverBackgroundColor = undefined;
                      return prev;
                    },
                  },
                ],
                panelId: clientId,
                hasColorsOrGradients: false,
                disableCustomColors: false,
                __experimentalIsRenderedInSidebar: true,
              },
              colorGradientSettings
            )
          )
        );
      }

      children.push(
        el(
          InspectorControls,
          { key: "hover-color-controls", group: "color" },
          colorChildren
        )
      );
    }

    // Border controls
    if (hasHoverBorder) {
      children.push(
        el(
          InspectorControls,
          { key: "hover-border-controls", group: "border" },
          el(
            ToolsPanelItem,
            {
              panelId: clientId,
              hasValue: function () {
                return Object.keys(hoverBorder || {}).length > 0;
              },
              label: __("Hover border", "brandy"),
              onDeselect: function () {
                setAttributes({
                  style: Object.assign({}, attributes.style || {}, {
                    hoverBorder: {},
                  }),
                });
              },
              resetAllFilter: function (prev) {
                prev.style.hoverBorder = {};
                return prev;
              },
              isShownByDefault: true,
            },
            el(BorderBoxControl, {
              colors: colorGradientSettings.colors || [],
              panelId: clientId,
              value: hoverBorder,
              onChange: function (v) {
                setAttributes({
                  style: Object.assign({}, attributes.style || {}, {
                    hoverBorder: v,
                  }),
                });
              },
              enableAlpha: true,
              popoverOffset: 40,
              popoverPlacement: "left-start",
              __experimentalIsRenderedInSidebar: true,
              size: "__unstable-large",
              label: __("Hover border", "brandy"),
            })
          )
        )
      );
    }

    return el(Fragment, null, children);
  }

  // ── Attribute registration filter ─────────────────────────────────

  function registerHoverSettingsAttributes(settings) {
    if (typeof settings.attributes === "undefined") {
      return settings;
    }

    if (!settings.attributes.style) {
      settings.attributes.style = {};
    }

    var newAttributes = {};

    if (isBlockSupportBackgroundColor(settings.name)) {
      newAttributes.hoverBackgroundColor = { type: "string", default: "" };
    }
    if (isBlockSupportTextColor(settings.name)) {
      newAttributes.hoverTextColor = { type: "string", default: "" };
    }
    if (isBlockSupportBorder(settings.name)) {
      newAttributes.hoverBorder = { type: "object", default: {} };
    }

    settings.attributes.style = Object.assign(
      settings.attributes.style,
      newAttributes
    );

    return settings;
  }

  // ── Editor BlockEdit HOC ──────────────────────────────────────────

  var addHoverSettingsControls = createHigherOrderComponent(
    function (BlockEdit) {
      return function (props) {
        var isSelected = props.isSelected;
        var blockName = props.name;
        var canAddSettings =
          isBlockSupportBackgroundColor(blockName) ||
          isBlockSupportTextColor(blockName) ||
          isBlockSupportBorder(blockName);

        return el(
          Fragment,
          null,
          el(BlockEdit, props),
          isSelected && canAddSettings && el(HoverSettingsPanel, props)
        );
      };
    },
    "addHoverSettingsControls"
  );

  // ── Editor BlockListBlock HOC ─────────────────────────────────────

  var addHoverSettingsStyleToBlock = createHigherOrderComponent(
    function (BlockListBlock) {
      return function (props) {
        var attributes = props.attributes;
        var extraWrapperProps = Object.assign({}, props.wrapperProps || {});
        var hoverBackgroundColor =
          attributes.style && attributes.style.hoverBackgroundColor;
        var hoverTextColor =
          attributes.style && attributes.style.hoverTextColor;
        var hoverBorder = attributes.style && attributes.style.hoverBorder;
        var styleKeys = attributes.style ? Object.keys(attributes.style) : [];

        if (
          styleKeys.indexOf("hoverBackgroundColor") !== -1 &&
          hoverBackgroundColor
        ) {
          extraWrapperProps.style = Object.assign(
            {},
            extraWrapperProps.style || {},
            { "--hover-background-color": hoverBackgroundColor }
          );
        }

        if (styleKeys.indexOf("hoverTextColor") !== -1 && hoverTextColor) {
          extraWrapperProps.style = Object.assign(
            {},
            extraWrapperProps.style || {},
            { "--hover-color": hoverTextColor }
          );
        }

        if (styleKeys.indexOf("hoverBorder") !== -1 && hoverBorder) {
          extraWrapperProps.style = Object.assign(
            {},
            extraWrapperProps.style || {},
            getBorderHoverStyleFromAttributes(attributes, props)
          );
        }

        return el(
          BlockListBlock,
          Object.assign({}, props, { wrapperProps: extraWrapperProps })
        );
      };
    },
    "addHoverSettingsStyleToBlock"
  );

  // ── Register filters ──────────────────────────────────────────────

  addFilter(
    "blocks.registerBlockType",
    "brandy/hover-settings-attributes",
    registerHoverSettingsAttributes
  );

  addFilter(
    "editor.BlockEdit",
    "brandy/hover-settings-controls",
    addHoverSettingsControls,
    9
  );

  addFilter(
    "editor.BlockListBlock",
    "brandy/hover-settings-style",
    addHoverSettingsStyleToBlock
  );
})();
