'use client';
import dedent from 'dedent';
import { assert } from 'emery';
import { forwardRef, createContext, useContext, Fragment } from 'react';
import { jsx } from 'react/jsx-runtime';
import { useLink } from '@react-aria/link';
import { mergeProps, useObjectRef } from '@react-aria/utils';
import { useFocusRing } from '@react-aria/focus';
import { useHover } from '@react-aria/interactions';
import { tokenSchema, classNames, css } from '@keystar/ui/style';
import { useHeadingContext, useTextContext, Text } from '@keystar/ui/typography';
import { toDataAttributes } from '@keystar/ui/utils';
import { useButton } from '@react-aria/button';

const makeLinkComponent = render => ({
  __forwardRef__: /*#__PURE__*/forwardRef(render)
});
const DefaultLinkComponent = makeLinkComponent((props, ref) => /*#__PURE__*/jsx("a", {
  ref: ref,
  ...props
}));
const LinkComponentContext = /*#__PURE__*/createContext(DefaultLinkComponent);
const useLinkComponent = ref => {
  const linkComponent = useContext(LinkComponentContext);
  assert(!ref || '__forwardRef__' in linkComponent, dedent`
      You're passing a ref to a Keystar UI link, but your app is providing a custom link component to 'VoussoirProvider' that doesn't appear to support refs.

      To fix this, you need to use Keystar UI'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.
    `);
  if ('__forwardRef__' in linkComponent) {
    return linkComponent.__forwardRef__;
  }
  return linkComponent;
};

function useTextLink(_ref) {
  let {
    autoFocus,
    prominence = 'default'
  } = _ref;
  const headingContext = useHeadingContext();
  const textContext = useTextContext();
  const {
    focusProps,
    isFocusVisible
  } = useFocusRing({
    autoFocus
  });
  const {
    hoverProps,
    isHovered
  } = useHover({});
  const fontWeight = headingContext ? undefined : tokenSchema.typography.fontWeight.medium;
  const dataOptions = {
    prominence,
    hover: isHovered ? 'true' : undefined,
    focus: isFocusVisible ? 'visible' : undefined
  };
  return {
    ...mergeProps(hoverProps, focusProps),
    ...toDataAttributes(dataOptions),
    Wrapper: !textContext && !headingContext ? Text : Fragment,
    className: classNames(css({
      color: tokenSchema.color.foreground.neutral,
      cursor: 'pointer',
      fontWeight,
      outline: 0,
      textDecoration: 'underline',
      textDecorationColor: tokenSchema.color.border.emphasis,
      textDecorationThickness: tokenSchema.size.border.regular,
      textUnderlineOffset: tokenSchema.size.border.medium,
      '&[data-hover="true"], &[data-focus="visible"]': {
        color: tokenSchema.color.foreground.neutralEmphasis,
        textDecorationColor: tokenSchema.color.foreground.neutral
      },
      '&[data-focus="visible"]': {
        textDecorationStyle: 'double'
      },
      '&[data-prominence="high"]': {
        color: tokenSchema.color.foreground.accent,
        textDecorationColor: tokenSchema.color.border.accent,
        '&[data-hover="true"], &[data-focus="visible"]': {
          textDecorationColor: tokenSchema.color.foreground.accent
        }
      }
    }))
  };
}

/** @private Forked variant where an "href" is provided. */
const TextLinkAnchor = /*#__PURE__*/forwardRef(function TextLink(props, forwardedRef) {
  const {
    children,
    download,
    href,
    hrefLang,
    ping,
    referrerPolicy,
    rel,
    target,
    ...otherProps
  } = props;
  const LinkComponent = useLinkComponent(forwardedRef);
  const domRef = useObjectRef(forwardedRef);
  const {
    Wrapper,
    ...styleProps
  } = useTextLink(props);
  const {
    linkProps
  } = useLink(otherProps, domRef);
  return /*#__PURE__*/jsx(Wrapper, {
    children: /*#__PURE__*/jsx(LinkComponent, {
      ref: domRef,
      download: download,
      href: href,
      hrefLang: hrefLang,
      ping: ping,
      referrerPolicy: referrerPolicy,
      rel: rel,
      target: target,
      ...mergeProps(linkProps, styleProps),
      children: children
    })
  });
});

const TextLinkButton = /*#__PURE__*/forwardRef(function TextLink(props, forwardedRef) {
  const {
    children,
    ...otherProps
  } = props;
  const domRef = useObjectRef(forwardedRef);
  const {
    Wrapper,
    ...styleProps
  } = useTextLink(otherProps);
  const {
    buttonProps
  } = useButton({
    elementType: 'span',
    ...otherProps
  }, domRef);
  return /*#__PURE__*/jsx(Wrapper, {
    children: /*#__PURE__*/jsx("span", {
      ref: domRef,
      ...mergeProps(buttonProps, styleProps),
      children: children
    })
  });
});

/**
 * Text links take users to another place in the application, and usually appear
 * within or directly following a sentence. Styled to resemble a hyperlink.
 */
const TextLink = /*#__PURE__*/forwardRef(function TextLink(props, forwardedRef) {
  if ('href' in props) {
    return /*#__PURE__*/jsx(TextLinkAnchor, {
      ...props,
      ref: forwardedRef
    });
  }
  return /*#__PURE__*/jsx(TextLinkButton, {
    ...props,
    ref: forwardedRef
  });
});

export { DefaultLinkComponent, LinkComponentContext, TextLink, makeLinkComponent, useLinkComponent };
