import React, { useMemo, useCallback, useRef, useEffect, useContext } from 'react';
import { createDomRenderer, createDebouncedFn, createHead } from 'unhead/client';
import { ValidHeadTags, TagsWithInnerContent, HasElementTags } from 'unhead/utils';
import { U as UnheadContext } from './shared/react.DF9T1fqs.mjs';

let _singletonHead = null;
function useHelmetHead() {
  const ctx = useContext(UnheadContext);
  if (ctx) {
    return ctx;
  }
  if (!_singletonHead) {
    if (typeof window === "undefined") {
      throw new TypeError("Helmet requires UnheadProvider on the server. Wrap your app with <UnheadProvider>.");
    }
    const domRenderer = createDomRenderer();
    let head;
    const debouncedRenderer = createDebouncedFn(() => domRenderer(head), (fn) => setTimeout(fn, 0));
    head = createHead({ render: debouncedRenderer });
    _singletonHead = head;
  }
  return _singletonHead;
}
const Helmet = ({
  children,
  defaultTitle,
  titleTemplate,
  onChangeClientState,
  title: titleProp,
  base: baseProp,
  meta: metaProp,
  link: linkProp,
  script: scriptProp,
  style: styleProp,
  noscript: noscriptProp,
  htmlAttributes,
  bodyAttributes,
  // accepted for compat, intentionally unused
  encodeSpecialCharacters: _encodeSpecialCharacters,
  defer: _defer
}) => {
  const head = useHelmetHead();
  const processedElements = useMemo(() => React.Children.toArray(children).filter(React.isValidElement), [children]);
  const getHeadChanges = useCallback(() => {
    const input = {};
    if (titleTemplate) {
      input.titleTemplate = titleTemplate;
    }
    if (titleProp != null) {
      input.title = titleProp;
    }
    if (baseProp) {
      input.base = baseProp;
    }
    if (metaProp) {
      input.meta = [...metaProp];
    }
    if (linkProp) {
      input.link = [...linkProp];
    }
    if (scriptProp) {
      input.script = [...scriptProp];
    }
    if (styleProp) {
      input.style = [...styleProp];
    }
    if (noscriptProp) {
      input.noscript = [...noscriptProp];
    }
    if (htmlAttributes) {
      input.htmlAttrs = htmlAttributes;
    }
    if (bodyAttributes) {
      input.bodyAttrs = bodyAttributes;
    }
    let hasTitle = !!titleProp;
    for (const element of processedElements) {
      const reactElement = element;
      const { type, props } = reactElement;
      let tagName = String(type);
      if (tagName === "html")
        tagName = "htmlAttrs";
      else if (tagName === "body")
        tagName = "bodyAttrs";
      if (!ValidHeadTags.has(tagName)) {
        continue;
      }
      const data = { ...typeof props === "object" ? props : {} };
      if (TagsWithInnerContent.has(tagName) && data.children != null) {
        const contentKey = tagName === "script" ? "innerHTML" : "textContent";
        data[contentKey] = Array.isArray(data.children) ? data.children.map(String).join("") : String(data.children);
      }
      delete data.children;
      if (tagName === "title") {
        hasTitle = true;
      }
      if (HasElementTags.has(tagName)) {
        const key = tagName;
        if (!Array.isArray(input[key])) {
          input[key] = [];
        }
        input[key].push(data);
      } else {
        input[tagName] = data;
      }
    }
    if (!hasTitle && defaultTitle) {
      input.title = defaultTitle;
    }
    if (defaultTitle) {
      input.templateParams = {
        ...input.templateParams,
        defaultTitle
      };
    }
    return input;
  }, [processedElements, titleTemplate, defaultTitle, titleProp, baseProp, metaProp, linkProp, scriptProp, styleProp, noscriptProp, htmlAttributes, bodyAttributes]);
  const headRef = useRef(null);
  const onChangeClientStateRef = useRef(onChangeClientState);
  onChangeClientStateRef.current = onChangeClientState;
  if (head.ssr && !headRef.current) {
    headRef.current = head.push(getHeadChanges());
  }
  useEffect(() => {
    const options = {
      onRendered: () => {
        const cb = onChangeClientStateRef.current;
        if (!cb)
          return;
        const titleEl = document.querySelector("title");
        const state = {
          title: titleEl?.textContent || ""
        };
        for (const tag of ["meta", "link", "script", "style", "base"]) {
          state[`${tag}Tags`] = Array.from(document.querySelectorAll(`head ${tag}`));
        }
        cb(state, {}, {});
      }
    };
    headRef.current = head.push(getHeadChanges(), options);
    return () => {
      headRef.current?.dispose();
      headRef.current = null;
    };
  }, [head]);
  useEffect(() => {
    headRef.current?.patch(getHeadChanges());
  }, [getHeadChanges]);
  return null;
};

export { Helmet };
