import cx from "classnames";
import React from "react";
import { TagButtonProps } from "./TagButton";

export const colors = [
  "black",
  "orange",
  "yellow",
  "green",
  "blue",
  "success",
  "info",
  "warning",
  "danger",
  "transparent",
] as const;

export type TagColor = (typeof colors)[number];
export type TagSize = "small" | "large";

interface CommonProps {
  color?: TagColor;
  size?: TagSize;
  isDisabled?: boolean;
  className?: string;
  children?: React.ReactNode;
  actionButton?: React.ReactElement<TagButtonProps>;
}

type SpanProps = CommonProps &
  Omit<React.HTMLAttributes<HTMLSpanElement>, keyof CommonProps> & {
    onClick?: undefined;
    href?: undefined;
  };

type ButtonProps = CommonProps &
  Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, keyof CommonProps> & {
    onClick: React.MouseEventHandler<HTMLButtonElement>;
    href?: undefined;
  };

type AnchorProps = CommonProps &
  Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof CommonProps> & {
    href: string;
    onClick?: undefined;
  };

type TagProps = SpanProps | ButtonProps | AnchorProps;

export const CLASS_ROOT = "tag";

const Tag = React.forwardRef<HTMLElement, TagProps>((props, ref) => {
  const {
    color,
    size,
    isDisabled,
    className,
    children,
    actionButton,
    ...other
  } = props;

  const classes = cx(CLASS_ROOT, className, {
    [`tag--${color}`]: color,
    [`tag--${size}`]: size,
  });

  if ("onClick" in props && props.onClick) {
    const { onClick, ...buttonProps } =
      other as React.ButtonHTMLAttributes<HTMLButtonElement>;
    return (
      <button
        type="button"
        className={classes}
        onClick={onClick}
        disabled={isDisabled ? true : undefined}
        aria-disabled={isDisabled ? "true" : undefined}
        ref={ref as React.Ref<HTMLButtonElement>}
        {...buttonProps}
      >
        {children}
      </button>
    );
  }

  if ("href" in props && props.href) {
    const { href, ...anchorProps } =
      other as React.AnchorHTMLAttributes<HTMLAnchorElement>;
    return (
      <a
        className={classes}
        href={href}
        aria-disabled={isDisabled ? "true" : undefined}
        ref={ref as React.Ref<HTMLAnchorElement>}
        {...anchorProps}
      >
        {children}
      </a>
    );
  }

  if ("actionButton" in props && actionButton) {
    const spanProps = other as Omit<
      React.HTMLAttributes<HTMLDivElement>,
      "onClick"
    >;
    return (
      <div
        ref={ref as React.Ref<HTMLDivElement>}
        className={`${CLASS_ROOT}__wrapper`}
      >
        <span
          className={classes}
          aria-disabled={isDisabled ? "true" : undefined}
          {...spanProps}
        >
          {children}
        </span>
        {React.isValidElement(actionButton)
          ? React.cloneElement(actionButton, { size, isDisabled })
          : actionButton}
      </div>
    );
  }

  const spanProps = other as React.HTMLAttributes<HTMLSpanElement>;
  return (
    <span
      className={classes}
      ref={ref as React.Ref<HTMLSpanElement>}
      {...spanProps}
    >
      {children} {actionButton}
    </span>
  );
});

Tag.displayName = "Tag";

export { Tag };
