import React, { forwardRef, useCallback } from 'react';
import { clsx } from 'clsx';
import type { PrimitiveAnchorProps } from '.';

/**
 * The Primitive `PrimitiveAnchor` component is customisable link element that can be
 * used in various parts of the Wise Design System internally. It supports
 * different states such as disabled and provides event handlers for common
 * interactions like click, focus, blur, mouse enter, mouse leave, and key down.
 *
 * @see {@link PrimitiveAnchor} for further information.
 * @see {@link https://storybook.wise.design/?path=/docs/primitive-anchor--docs|Storybook Wise Design}
 */
const PrimitiveAnchor = forwardRef<HTMLAnchorElement, PrimitiveAnchorProps>(
  (
    {
      children,
      className,
      href,
      id,
      disabled = false,
      testId,
      onClick,
      onFocus,
      onBlur,
      onMouseEnter,
      onMouseLeave,
      onKeyDown,
      ...props
    },
    ref,
  ) => {
    const anchorClasses = clsx(className);

    const handleClick = useCallback(
      (event: React.MouseEvent<HTMLAnchorElement>) => {
        if (disabled) {
          event.preventDefault();
        } else {
          onClick?.(event);
        }
      },
      [disabled, onClick],
    );

    const handleFocus = useCallback(
      (event: React.FocusEvent<HTMLAnchorElement>) => {
        onFocus?.(event);
      },
      [onFocus],
    );

    const handleBlur = useCallback(
      (event: React.FocusEvent<HTMLAnchorElement>) => {
        onBlur?.(event);
      },
      [onBlur],
    );

    const handleMouseEnter = useCallback(
      (event: React.MouseEvent<HTMLAnchorElement>) => {
        onMouseEnter?.(event);
      },
      [onMouseEnter],
    );

    const handleMouseLeave = useCallback(
      (event: React.MouseEvent<HTMLAnchorElement>) => {
        onMouseLeave?.(event);
      },
      [onMouseLeave],
    );

    const handleKeyDown = useCallback(
      (event: React.KeyboardEvent<HTMLAnchorElement>) => {
        onKeyDown?.(event);
      },
      [onKeyDown],
    );

    /**
     * The following props are set to handle the `disabled` state for the link:
     *
     * - `aria-disabled`: Exposes the link as disabled to assistive technologies.
     * - `href`: Removed when `disabled` is true to prevent navigation.
     * - `role`: Set to 'link' when `disabled` is true to ensure the element
     *    is still exposed as a link.
     *
     * For more details, refer to Scott O'Hara's article on disabling links:
     * https://www.scottohara.me/blog/2021/05/28/disabled-links.html
     */
    const anchorProps = {
      'aria-disabled': disabled || undefined,
      className: anchorClasses,
      'data-testid': testId,
      href: disabled ? undefined : href,
      id,
      ref,
      role: disabled ? 'link' : undefined,
      rel: props.target === '_blank' ? 'noopener noreferrer' : undefined,
      onClick: handleClick,
      onFocus: handleFocus,
      onBlur: handleBlur,
      onMouseEnter: handleMouseEnter,
      onMouseLeave: handleMouseLeave,
      onKeyDown: handleKeyDown,
      ...props,
    };

    return <a {...anchorProps}>{children}</a>;
  },
);

PrimitiveAnchor.displayName = 'PrimitiveAnchor';

export default PrimitiveAnchor;
