import * as React from 'react';
import { Button, tailwind } from '@tesseract-design/web-base';

const { tw } = tailwind;

const LinkButtonDerivedElementComponent = 'a' as const;

/**
 * Derived HTML element of the {@link LinkButton} component.
 */
export type LinkButtonDerivedElement = HTMLElementTagNameMap[
	typeof LinkButtonDerivedElementComponent
];

interface LinkButtonCommonProps extends Omit<React.HTMLProps<LinkButtonDerivedElement>, 'href' | 'size'> {
	/**
	 * Should the component occupy the whole width of its parent?
	 */
	block?: boolean;
	/**
	 * Variant of the component.
	 */
	variant?: Button.Variant;
	/**
	 * Complementary content of the component.
	 */
	subtext?: React.ReactNode;
	/**
	 * Short complementary content displayed at the edge of the component.
	 */
	badge?: React.ReactNode;
	/**
	 * Is this component part of a menu?
	 */
	menuItem?: boolean;
	/**
	 * Size of the component.
	 */
	size?: Button.Size;
	/**
	 * Should the component's content use minimal space?
	 */
	compact?: boolean;
	/**
	 * Is the component unable to receive activation?
	 */
	disabled?: boolean;
	/**
	 * Graphical representation of the component.
	 */
	icon?: React.ReactNode;
	/**
	 * Should the graphical representation of the component be placed after the children?
	 */
	iconAfterChildren?: boolean;
}

interface LinkButtonAnchorProps extends Pick<React.HTMLProps<LinkButtonDerivedElement>, 'href'> {
	component: typeof LinkButtonDerivedElementComponent;
}

interface LinkButtonComponentType {
	(props: { href?: string }): React.ReactNode;
}

interface LinkButtonFCProps<
	C extends LinkButtonComponentType = LinkButtonComponentType
> {
	component: C;
	href: C extends (props: { href?: infer Href }) => React.ReactNode ? Href : never;
}

type LinkButtonAllProps<
	T extends LinkButtonComponentType = LinkButtonComponentType
> =
	LinkButtonAnchorProps | LinkButtonFCProps<T>;

/**
 * Props of the {@link LinkButton} component.
 */
export type LinkButtonProps<
	T extends LinkButtonComponentType = LinkButtonComponentType
> =
	LinkButtonCommonProps & LinkButtonAllProps<T>;

/**
 * Component for performing a navigation action.
 */
export const LinkButton = React.forwardRef<LinkButtonDerivedElement, LinkButtonProps>((
  {
    variant = 'bare' as const,
    subtext,
    badge,
    menuItem = false,
    children,
    size = 'medium' as const,
    compact = false,
    className,
    block = false,
    component: EnabledComponent = LinkButtonDerivedElementComponent,
    disabled = false,
    href,
    style,
		icon,
		iconAfterChildren = false as const,
    ...etcProps
  },
  forwardedRef,
) => {
  const Component = (disabled ? 'button' : EnabledComponent) as typeof LinkButtonDerivedElementComponent;
	const extraProps = {
		disabled: disabled || undefined,
	};

  return (
    <Component
      {...etcProps}
			{...extraProps}
      href={disabled ? undefined : href as string}
      type={disabled ? 'button' : undefined}
      ref={forwardedRef}
      className={tw(
        'items-center justify-center rounded overflow-hidden ring-secondary/50 leading-none select-none no-underline m-0',
        'focus:outline-0 focus:ring-4',
        'active:ring-tertiary/50',
        'disabled:opacity-50 disabled:cursor-not-allowed',
        {
          'flex w-full': block,
          'inline-flex max-w-full align-middle': !block,
        },
        {
          'pl-2 gap-2': compact,
          'pl-4 gap-4': !compact,
          'pr-4': !(compact || menuItem),
          'pr-2': compact || menuItem,
        },
        {
          'border-2 border-primary focus:border-secondary active:border-tertiary disabled:border-primary': variant !== 'bare',
          'bg-negative text-primary focus:text-secondary active:text-tertiary disabled:text-primary': variant !== 'filled',
          'bg-primary text-negative focus:bg-secondary active:bg-tertiary focus:text-negative active:text-negative disabled:bg-primary': variant === 'filled',
        },
        {
          'h-10': size === 'small',
          'h-12': size === 'medium',
          'h-16': size === 'large',
        },
        className,
      )}
      data-testid="link"
      style={style}
    >
      <span
				data-testid="childrenParent"
				className={tw(
					'flex-auto min-w-0 flex items-center gap-2',
					iconAfterChildren ? 'flex-row-reverse' : 'flex-row',
				)}
      >
				{icon && (
					<span
						data-testid="icon"
					>
						{icon}
					</span>
				)}
				{(children || subtext) && (
					<span
						className={tw(
							'min-w-0 flex-auto',
							{
								'text-left': compact || menuItem,
								'text-center': !(compact || menuItem),
							},
						)}
					>
						{children && (
							<span
								className={tw(
									'block uppercase font-bold w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded h-[1.1em]',
								)}
								data-testid="children"
							>
								{children}
							</span>
						)}
						{subtext && (
							<>
								<span className="sr-only">
									{' - '}
								</span>
								<span
									className="block h-[1.3em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded font-bold text-xs"
									data-testid="subtext"
								>
									{subtext}
								</span>
							</>
						)}
					</span>
				)}
      </span>
      {badge && (
        <>
          <span className="sr-only">
            {' - '}
          </span>
          <span
            data-testid="badge"
          >
            {badge}
          </span>
        </>
      )}
      {menuItem && (
        <span
          data-testid="menuItemIndicator"
        >
          <svg
            className="w-6 h-6 fill-none stroke-current stroke-2 linejoin-round linecap-round"
            viewBox="0 0 24 24"
            role="presentation"
          >
            <polyline points="9 18 15 12 9 6" />
          </svg>
        </span>
      )}
    </Component>
  );
});

LinkButton.displayName = 'LinkButton';

LinkButton.defaultProps = {
  variant: 'bare' as const,
  size: 'medium' as const,
  compact: false as const,
  menuItem: false as const,
  badge: undefined,
  subtext: undefined,
  block: false as const,
  disabled: false as const,
	icon: undefined,
	iconAfterChildren: false as const,
	// eslint-disable-next-line react/default-props-match-prop-types
	component: LinkButtonDerivedElementComponent,
	// eslint-disable-next-line react/default-props-match-prop-types
	href: undefined,
};

// extend the component type here for defining new props
// interface LinkButtonComponentType {
// 	(props: { href?: number }): React.ReactNode;
// }

// const CustomLink = (props: { href?: string | number }) => {
// 	return null;
// };
//
// const a = (
// 	<LinkButton
// 		component="a"
// 		href="string"
// 	/>
// );
