import { jsx, jsxs } from "react/jsx-runtime";
import assert from "assert";
import dedent from "dedent";
import { useEffect, createContext, useState, useContext, forwardRef } from "react";
import { ensureResetImported } from "../../css/reset/resetTracker.mjs";
import { hideFocusRingsDataAttribute } from "../../../../styles/lib/components/private/hideFocusRings/hideFocusRingsDataAttribute.mjs";
import { breakpoints } from "../../../../styles/lib/css/breakpoints.mjs";
import { darkMode } from "../../../../styles/lib/css/atoms/sprinkles.css.mjs";
import { VanillaThemeContainer } from "../../../../styles/lib/components/BraidProvider/VanillaThemeContainer.mjs";
const hideFocusRings = () => document.body.setAttribute(hideFocusRingsDataAttribute, "true");
const showFocusRings = () => document.body.removeAttribute(hideFocusRingsDataAttribute);
const useHideFocusRings = (enabled = true) => {
  useEffect(() => {
    if (enabled) {
      window.addEventListener("keydown", showFocusRings);
      window.addEventListener("mousemove", hideFocusRings);
      return () => {
        window.removeEventListener("keydown", showFocusRings);
        window.removeEventListener("mousemove", hideFocusRings);
      };
    }
  }, [enabled]);
};
const BraidTestProviderContext = createContext(false);
const minWidthQuery = (breakpoint) => window.matchMedia(`(min-width: ${breakpoint}px)`);
const getCurrentBreakpoint = (tabletQuery, desktopQuery, wideQuery) => {
  if (wideQuery.matches) {
    return "wide";
  }
  if (desktopQuery.matches) {
    return "desktop";
  }
  if (tabletQuery.matches) {
    return "tablet";
  }
  return "mobile";
};
const breakpointContext = createContext(null);
function BreakpointProvider({ children }) {
  const { tablet, desktop, wide } = breakpoints;
  const [state, setState] = useState(null);
  useEffect(() => {
    let mounted = true;
    const tabletQuery = minWidthQuery(tablet);
    const desktopQuery = minWidthQuery(desktop);
    const wideQuery = minWidthQuery(wide);
    const onChange = () => {
      if (!mounted) {
        return;
      }
      const newBreakPoint = getCurrentBreakpoint(
        tabletQuery,
        desktopQuery,
        wideQuery
      );
      if (newBreakPoint !== state) {
        setState(newBreakPoint);
      }
    };
    tabletQuery.addListener(onChange);
    desktopQuery.addListener(onChange);
    wideQuery.addListener(onChange);
    onChange();
    return () => {
      mounted = false;
      tabletQuery.removeListener(onChange);
      desktopQuery.removeListener(onChange);
      wideQuery.removeListener(onChange);
    };
  }, [tablet, desktop, wide, state]);
  return /* @__PURE__ */ jsx(breakpointContext.Provider, { value: state, children });
}
const BraidThemeContext = createContext(null);
const useBraidTheme = () => {
  const braidTheme = useContext(BraidThemeContext);
  if (braidTheme === null) {
    throw new Error("No Braid theme available on context");
  }
  return braidTheme;
};
if (process.env.NODE_ENV === "development") {
  ensureResetImported();
}
const makeLinkComponent = (render) => ({ __forwardRef__: forwardRef(render) });
const DefaultLinkComponent = makeLinkComponent((props, ref) => /* @__PURE__ */ jsx("a", { ref, ...props }));
const LinkComponentContext = createContext(DefaultLinkComponent);
const useLinkComponent = (ref) => {
  const linkComponent = useContext(LinkComponentContext);
  assert(
    !ref || "__forwardRef__" in linkComponent,
    dedent`
      You're passing a ref to a Braid link, but your app is providing a custom link component to 'BraidProvider' that doesn't appear to support refs.

      To fix this, you need to use Braid's 'makeLinkComponent' helper function when creating your custom link component. This ensures that refs are forwarded correctly, and allows us to silence this error message.

      For more information and an example implementation, check out the documentation for 'BraidProvider': https://seek-oss.github.io/braid-design-system/components/BraidProvider
    `
  );
  if ("__forwardRef__" in linkComponent) {
    return linkComponent.__forwardRef__;
  }
  return linkComponent;
};
const BraidProvider = ({
  theme,
  styleBody = true,
  linkComponent,
  children
}) => {
  const alreadyInBraidProvider = Boolean(useContext(BraidThemeContext));
  const inTestProvider = useContext(BraidTestProviderContext);
  const linkComponentFromContext = useContext(LinkComponentContext);
  useHideFocusRings(!(alreadyInBraidProvider || inTestProvider));
  assert(
    inTestProvider || typeof navigator === "undefined" || navigator.userAgent === void 0 || navigator.userAgent.indexOf("jsdom") === -1,
    `Rendering 'BraidProvider' in Jest is not supported as it expects a browser environment. Please switch to 'BraidTestProvider'. See the docs for more info: https://seek-oss.github.io/braid-design-system/components/BraidTestProvider`
  );
  return /* @__PURE__ */ jsxs(BraidThemeContext.Provider, { value: theme, children: [
    styleBody ? /* @__PURE__ */ jsx("style", { type: "text/css", children: `
            html,body{margin:0;padding:0;background:${theme.background.lightMode}}
            html.${darkMode},html.${darkMode} body{color-scheme:dark;background:${theme.background.darkMode}}
          ` }) : null,
    /* @__PURE__ */ jsx(
      VanillaThemeContainer,
      {
        theme: theme.vanillaTheme,
        setDefaultTextTones: !alreadyInBraidProvider,
        children: /* @__PURE__ */ jsx(
          LinkComponentContext.Provider,
          {
            value: linkComponent || linkComponentFromContext,
            children: alreadyInBraidProvider || inTestProvider ? children : /* @__PURE__ */ jsx(BreakpointProvider, { children })
          }
        )
      }
    )
  ] });
};
export {
  BraidProvider,
  BraidTestProviderContext,
  breakpointContext,
  makeLinkComponent,
  useBraidTheme,
  useLinkComponent
};
