import { FC, forwardRef, memo, ReactNode } from 'react';
import type { AnchorHTMLAttributes, MouseEventHandler, SyntheticEvent } from 'react';
import { Link as ReactLink } from 'react-router-dom';
import clsx from 'clsx';

import { styled } from '@mui/material/styles';
import { SxProps } from '@mui/system';
import type { Theme } from '../../@styles/theme-provider';

const HYPERLINK_PREFIXES = ['http', 'mailto'];

const componentStyles = ({ theme }: { theme: Theme }) => ({
  color: 'inherit',
  '&, &:hover': {
    textDecoration: 'none'
  },
  '&.table': {
    color: theme.palette.secondary[500],
    '&:hover': {
      color: theme.palette.secondary[600],
      cursor: 'pointer'
    }
  }
});

const StyledAnchor = styled('a')(componentStyles);

const StyledReactLink = styled(ReactLink)(componentStyles);

export interface LinkProps<T = unknown> extends Omit<AnchorHTMLAttributes<T>, 'href'> {
  /**
   * The component which display the link.
   */
  children?: ReactNode;
  /**
   * The href the link will address to.
   */
  href?:
    | string
    | { search?: string; pathname?: string; hash?: string }
    | MouseEventHandler<HTMLButtonElement>;
  /**
   * Apply special styles for table link?
   */
  table?: boolean;
  classes?: {
    root?: string;
  };
  onClick?: (e: SyntheticEvent<EventTarget>) => void;
  sx?: SxProps<Theme>;
}

const Link: FC<LinkProps<unknown>> = forwardRef<HTMLAnchorElement, LinkProps<unknown>>(
  (props, ref) => {
    const { children, className: cn, classes, href, table = false, onClick, ...otherProps } = props;

    const className = clsx((href || onClick) && [classes?.root, table && 'table'], cn);

    if (typeof href === 'string' && HYPERLINK_PREFIXES.some(v => href.startsWith(v))) {
      return (
        <StyledAnchor
          ref={ref}
          href={href}
          className={className}
          onClick={onClick}
          target="_blank"
          {...otherProps}
        >
          {children}
        </StyledAnchor>
      );
    }

    return href ? (
      <StyledReactLink ref={ref} to={href} className={className} onClick={onClick} {...otherProps}>
        {children}
      </StyledReactLink>
    ) : onClick !== undefined ? (
      <StyledAnchor className={className} onClick={onClick} {...otherProps}>
        {children}
      </StyledAnchor>
    ) : (
      // fallback in case no href/empty href is provided
      /* eslint-disable-next-line */
      <>{children}</>
    );
  }
);

const m = memo(Link);
export { m as Link };
