'use client';

import { classNames } from '@vkontakte/vkjs';
import { useAdaptivity } from '../../hooks/useAdaptivity';
import { type SizeTypeValues, ViewWidth, type ViewWidthType } from '../../lib/adaptivity';
import { mergeCalls } from '../../lib/mergeCalls';
import { checkClickable, Clickable, type ClickableProps } from '../Clickable/Clickable';
import { Ripple, useMaybeNeedRipple, useRipple } from './Ripple';
import { activeClass, DEFAULT_STATE_MODE, hoverClass, type StateProps } from './state';
import styles from './Tappable.module.css';

function getViewWidthClassName(
  viewWidth: ViewWidthType | 'none',
  legacySizeX: SizeTypeValues | undefined,
) {
  // TODO [>=10]: #9015 Удалить это условие
  if (legacySizeX !== undefined && legacySizeX === 'compact') {
    return styles.withBorder;
  }
  if (viewWidth === 'none') {
    return styles.withBorderOnSmallTabletMinus;
  }
  if (viewWidth < ViewWidth.SMALL_TABLET) {
    return styles.withBorder;
  }
  return;
}

function hasPointerClassName(hasPointer: boolean | undefined) {
  switch (hasPointer) {
    case undefined:
      return styles.hasPointerNone;
    case false:
      return styles.hasPointerFalse;
  }

  return undefined;
}

export interface TappableProps extends ClickableProps, StateProps {
  /**
   * Задает border-radius элементу
   * В режиме `auto` на маленьких экранах `border-radius: 0`, иначе определяется токеном `--vkui--size_border_radius--regular`.
   */
  borderRadiusMode?: 'auto' | 'inherit' | undefined;
  /**
   * @deprecated Since 7.3.0. Будет удалeно в **VKUI v9**.
   *
   * Используйте свойство `activeMode`.
   */
  activeClassName?: string | undefined; // TODO [>=9]: удалить неиспользуемое свойство.
  /**
   * @deprecated Since 7.3.0. Будет удалeно в **VKUI v9**.
   *
   * Используйте свойство `hoverMode`.
   */
  hoverClassName?: string | undefined; // TODO [>=9]: удалить неиспользуемое свойство.
}

/**
 * @deprecated Не наследуйтесь от этого типа и от TappableProps.
 *
 * Компонентам не нужны лишние свойства Tappable компонента.
 */
export type TappableOmitProps = Omit<
  TappableProps,
  'DefaultComponent' | 'baseClassName' | 'baseStyle'
>;

export const Tappable = ({
  baseClassName,
  borderRadiusMode = 'auto',
  children,
  hoverMode = DEFAULT_STATE_MODE,
  activeMode = DEFAULT_STATE_MODE,
  onPointerDown,
  onPointerCancel,
  ...restProps
}: TappableProps): React.ReactNode => {
  const isClickable = checkClickable(restProps);

  const { sizeX: legacySizeX, viewWidth = 'none', hasPointer } = useAdaptivity();

  const needRipple = useMaybeNeedRipple(activeMode, hasPointer);
  const { clicks, ...rippleEvents } = useRipple(needRipple, hasPointer);

  const handlers = mergeCalls(rippleEvents, {
    onPointerDown,
    onPointerCancel,
  });

  const typeProps = restProps.Component === 'button' ? { type: 'button' } : {};

  return (
    <Clickable
      baseClassName={classNames(
        'vkuiInternalTappable',
        baseClassName,
        styles.host,
        getViewWidthClassName(viewWidth, legacySizeX),
        borderRadiusMode === 'inherit' && styles.borderRadiusInherit,
        hasPointerClassName(hasPointer),
      )}
      hoverClassName={hoverClass(hoverMode)}
      activeClassName={activeClass(activeMode)}
      {...typeProps}
      {...handlers}
      {...restProps}
    >
      {children}
      {isClickable && (hoverMode === 'background' || activeMode === 'background') && (
        <Ripple needRipple={needRipple} clicks={clicks} />
      )}
    </Clickable>
  );
};
