'use client';

import * as React from 'react';
import { classNames, noop } from '@vkontakte/vkjs';
import { useAdaptivityWithJSMediaQueries } from '../../hooks/useAdaptivityWithJSMediaQueries';
import { usePlatform } from '../../hooks/usePlatform';
import { Keys, pressedKey } from '../../lib/accessibility';
import { warnOnce } from '../../lib/warnOnce';
import type { HasDataAttribute } from '../../types';
import { ActionSheetContext, type ActionSheetContextType } from '../ActionSheet/ActionSheetContext';
import { Tappable } from '../Tappable/Tappable';
import { Subhead } from '../Typography/Subhead/Subhead';
import { Text } from '../Typography/Text/Text';
import { Title } from '../Typography/Title/Title';
import { ActionSheetItemContext } from './context';
import { isRealClickEvent } from './helpers';
import { Radio } from './subcomponents/Radio/Radio';
import styles from './ActionSheetItem.module.css';

const warn = warnOnce('ActionSheetItem');

export interface ActionSheetItemProps
  extends React.HTMLAttributes<HTMLElement>,
    React.AnchorHTMLAttributes<HTMLElement>,
    HasDataAttribute,
    Pick<React.InputHTMLAttributes<HTMLInputElement>, 'name' | 'checked' | 'value'> {
  /**
   * Свойство, определяющее внешний вид элемента действия.
   *
   * > Since 8.0.0. Значение `"cancel"` устарело и будет удалено в **VKUI v10**.
   * > Используйте компонент `ActionSheetDefaultIosCloseItem` или передайте пропсы через `slotProps.iosCloseItem` в `ActionSheet`.
   */
  mode?: 'default' | 'destructive' | 'cancel' | undefined;
  /**
   * Если указано, элемент будет использоваться как ссылка.
   */
  href?: string | undefined;
  /**
   * Атрибут `target` для тега `<a>`.
   */
  target?: string | undefined;
  /**
   * Иконка или другой React-элемент для отображения перед основным контентом.
   */
  before?: React.ReactNode | undefined;
  /**
   * Иконка или другой React-элемент для отображения после основного контента.
   */
  after?: React.ReactNode | undefined;
  /**
   * Дополнительная информация, отображаемая рядом с основным контентом.
   */
  meta?: React.ReactNode | undefined;
  /**
   * Слот для подсказки или вспомогательного текста.
   */
  subtitle?: React.ReactNode | undefined;
  /**
   * По умолчанию нажатие на опцию вызывает переданную в `ActionSheet` функцию `onClose`, данное свойство
   * позволяет отключить такое поведение.
   */
  autoCloseDisabled?: boolean | undefined;
  /**
   * Включает возможность выбрать элемент (отображает радиокнопку).
   */
  selectable?: boolean | undefined;
  /**
   * Блокировка взаимодействия с компонентом.
   */
  disabled?: boolean | undefined;
  /**
   * Все текстовые элементы при необходимости занимают несколько строк.
   */
  multiline?: boolean | undefined;
  /**
   * По умолчанию `onClick` будет вызван после завершения анимации скрытия и после вызова `onClose`.
   * Из этого следует, что в объекте события значения полей типа `currentTarget` будут не определены.
   * Если вам нужен объект события именно на момент нажатия, используйте `onImmediateClick`.
   */
  onClick?: React.MouseEventHandler<HTMLElement> | undefined;
  /**
   * Обработчик нажатия, вызывающийся непосредственно в момент нажатия (в отличие от `onClick`).
   */
  onImmediateClick?: React.MouseEventHandler<HTMLElement> | undefined;
  /**
   * Иконка для `selectable` режима.
   */
  iconChecked?: React.ReactNode | undefined;
  /**
   * Позволяет отделить `ActionItem` от `CancelItem` для определении того,
   * кто вызвал закрытие `ActionSheet`. Используется в `ActionSheet.onClose()`.
   *
   * @deprecated Since 8.0.0. Свойство устарело и будет удалено в **VKUI v10**.
   * Используйте компонент `ActionSheetDefaultIosCloseItem` или передайте пропсы через `slotProps.iosCloseItem` в `ActionSheet`.
   */
  isCancelItem?: boolean | undefined;
}

/**
 * @see https://vkui.io/components/action-sheet#action-sheet-item
 */
export const ActionSheetItem = ({
  children,
  autoCloseDisabled = false,
  mode = 'default',
  meta,
  subtitle,
  before,
  after,
  selectable,
  value,
  name,
  checked,
  defaultChecked,
  onChange,
  onClick,
  onImmediateClick,
  multiline = false,
  iconChecked,
  isCancelItem: isCancelItemProp,
  ...restProps
}: ActionSheetItemProps): React.ReactNode => {
  const platform = usePlatform();
  const {
    onItemClick = () => noop,
    mode: actionSheetMode,
    onClose: onActionSheetClose,
  } = React.useContext<ActionSheetContextType<HTMLElement>>(ActionSheetContext);
  const { isCancelItem: isCancelItemFromContext } = React.useContext(ActionSheetItemContext);
  const { density } = useAdaptivityWithJSMediaQueries();

  if (process.env.NODE_ENV === 'development') {
    if (mode === 'cancel') {
      warn(
        'Свойство `mode="cancel"` устарело и будет удалено в VKUI v10. Используйте компонент `ActionSheetDefaultIosCloseItem` или передайте пропсы через `slotProps.iosCloseItem` в `ActionSheet`.',
      );
    }
    if (isCancelItemProp) {
      warn(
        'Свойство `isCancelItem` устарело и будет удалено в VKUI v10. Используйте компонент `ActionSheetDefaultIosCloseItem` или передайте пропсы через `slotProps.iosCloseItem` в `ActionSheet`.',
      );
    }
  }

  const isCancelItem = isCancelItemFromContext || !!isCancelItemProp;

  const isModeCancel = mode === 'cancel' || isCancelItemFromContext;

  const Component: React.ElementType | undefined = selectable ? 'label' : undefined;

  const isRich = subtitle || meta || selectable;
  const isCentered = !isRich && !before && platform === 'ios';

  const onItemClickHandler = React.useCallback(
    (e: React.MouseEvent) => {
      onItemClick({
        action: onClick,
        immediateAction: onImmediateClick,
        autoClose: !autoCloseDisabled,
        isCancelItem,
      })?.(e);
    },
    [autoCloseDisabled, isCancelItem, onClick, onImmediateClick, onItemClick],
  );

  const onKeyDown: React.KeyboardEventHandler<HTMLElement> = React.useCallback(
    (event) => {
      if (pressedKey(event) === Keys.ENTER) {
        onActionSheetClose?.('keydown-item');
      }
    },
    [onActionSheetClose],
  );

  const onItemClickImpl: React.MouseEventHandler<HTMLElement> = React.useCallback(
    (event) => {
      if (selectable) {
        if (isRealClickEvent(event)) {
          onItemClickHandler(event);
        }
      } else {
        onItemClickHandler(event);
      }
    },
    [onItemClickHandler, selectable],
  );

  return (
    <Tappable
      {...(Component && { Component })}
      {...restProps}
      onClick={onItemClickImpl}
      activeMode={platform === 'ios' ? styles.active : undefined}
      baseClassName={classNames(
        styles.host,
        platform === 'ios' && styles.ios,
        isModeCancel && styles.modeCancel,
        mode === 'destructive' && styles.modeDestructive,
        density === 'compact' && styles.densityCompact,
        isRich && styles.rich,
        actionSheetMode === 'menu' && styles.menu,
        restProps.disabled && styles.disabled,
      )}
      onKeyDown={onKeyDown}
    >
      {before && <div className={styles.before}>{before}</div>}
      <div className={classNames(styles.container, !multiline && styles.ellipsis)}>
        <div className={classNames(styles.content, isCentered && styles.centered)}>
          {platform === 'ios' ? (
            <Title
              className={styles.children}
              weight={isModeCancel ? '2' : '3'}
              level={isCentered ? '2' : '3'}
            >
              {children}
            </Title>
          ) : (
            <Text className={styles.children}>{children}</Text>
          )}
          {meta && <Text className={styles.meta}>{meta}</Text>}
        </div>
        {subtitle && <Subhead className={styles.subtitle}>{subtitle}</Subhead>}
      </div>
      {(selectable || after) && (
        <div className={styles.after}>
          {after}
          {selectable && (
            <Radio
              name={name}
              value={value}
              onChange={onChange}
              defaultChecked={defaultChecked}
              checked={checked}
              disabled={restProps.disabled}
            >
              {iconChecked}
            </Radio>
          )}
        </div>
      )}
    </Tappable>
  );
};
