import "./style.pcss";
import type {
  ButtonHTMLAttributes,
  MouseEvent,
  ReactElement,
  FC,
} from "react";
import {
  useEffect,
  useState,
} from "react";
import type { IBtn } from "./config/types";
import { constants } from "../../constants";
import type { IComponentBaseProps } from "../../types/components";
import { getExtraSizes } from "../../utils/getExtraSizes";
import { useCN } from "../../utils/react/useCN";
import { Icon } from "../icon/index";

const fallbackSize = constants.defaultSizes[2];

/**
 * Компонент кнопки
 * @returns {ReactElement}
 */
const Btn: FC<IBtn & IComponentBaseProps> = ({
  baseClass = "btn",
  href,
  type = "button",
  label = "Кнопка",
  title,
  isDisabled = false,
  isOutline = false,
  isLight = false,
  extraClasses = {},
  onClick,
  extraAttrs = {},
  icon = null,
  iconPosition = "left",
  iconSize,
  iconType,
  iconStyle,
  children,
  size = fallbackSize,
  form,
  target,
  id,
}): ReactElement => {

  const { getCN } = useCN(baseClass);

  const [ isDisabledState, setIsDisabledState ] = useState<boolean>(isDisabled);
  const [ btnLabel, setBtnLabel ] = useState<string | null>(label);
  const [ btnIcon, setBtnIcon ] = useState<string | null>(icon);

  useEffect(() => {
    setBtnIcon(icon as string);
  }, [ icon ]);

  useEffect(() => {
    setIsDisabledState(isDisabled as boolean);
  }, [ isDisabled ]);

  useEffect(() => {
    setBtnLabel(label as string);
  }, [ label ]);

  const iconLayout = !!btnIcon && <span className={getCN("icon")} {...(process.env.NODE_ENV === "test" ? { "data-testid": "btn-icon" } : {})}>
    <Icon src={btnIcon} size={iconSize || size} type={iconType} style={iconStyle} />
  </span>;

  const labelLayout = !!btnLabel && <span className={getCN("label")}>{btnLabel}</span>;

  const bodyLayout = children || ((iconPosition === "left") ? <>{iconLayout} {labelLayout}</> : <>{labelLayout} {iconLayout}</>);

  const classMods = getExtraSizes({
    size,
    extraClasses: {
      isOutline: isLight ? false : isOutline,
      isLight: isOutline ? false : isLight,
      isOnlyIcon: !btnLabel,
      ...extraClasses,
    },
  });

  const onLinkClick = (event: MouseEvent<HTMLAnchorElement>) => {
    if (isDisabled) {
      event.preventDefault();
      event.stopPropagation();
      return;
    }
    if (onClick) {
      onClick(event);
    }
  };

  const hasVisibleText = !!btnLabel || !!children;
  const computedAriaLabel = (!hasVisibleText && typeof title === "string" && title.length)
    ? title
    : undefined;
  const linkRole = href ? undefined : "button";

  return type === "link" ?
    <a title={title} id={id} role={linkRole} target={target} onClick={onLinkClick} href={isDisabled ? undefined : href}
      aria-disabled={isDisabled || undefined}
      aria-label={computedAriaLabel}
      tabIndex={isDisabled ? -1 : undefined}
      className={`${getCN("", classMods)} ${isDisabled ? constants.stateClasses.disabled : ""}`} {...extraAttrs}>
      {bodyLayout}
    </a> :
    <button title={title} id={id} form={form} draggable={false} onClick={onClick} type={type as ButtonHTMLAttributes<[]>["type"]}
      aria-label={computedAriaLabel}
      className={getCN("", classMods)}
      disabled={isDisabledState} {...extraAttrs}>
      {bodyLayout}
    </button>;
};

export type {
  IBtn,
};

export {
  Btn,
};

