import React, { useRef } from 'react';
import type { SilkeListItemData } from './types';
import { IEmojiIcon } from '@vev/utils';
import { isString } from 'lodash';
import { BoxButtonProps, BoxLinkProps, SilkeBox } from '../silke-box';
import { SilkeIcon, SilkeIcons } from '../silke-icon';
import { SilkeTag, SilkeTagProps } from '../silke-tag';
import { SilkePopoverNative } from '../silke-popover-native';
import { SilkeList } from './silke-list';
import { SilkeText } from '../silke-text';

import styles from './silke-list-item.scss';
import { SilkeImage } from '../silke-image';

type SilkeListItemProps = {
  label: string | React.ReactNode;
  subLabel?: string | React.ReactNode;
  icon?: IEmojiIcon | SilkeIcons | React.ReactElement;
  items?: SilkeListItemData[];
  link?: string;
  size?: 's' | 'base';
  tag?: SilkeTagProps;
  active?: boolean;
  gap?: boolean;
  maxHeight?: number;
  children?: React.ReactNode;
  alwaysShowChildren?: boolean;
  onClick?: (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void;
  onSelect?: () => void;
} & Omit<React.ComponentProps<typeof SilkeBox>, 'children' | 'tag'>;

export const SilkeListItem = ({
  label,
  subLabel,
  icon,
  items,
  link,
  tag,
  active,
  size,
  gap,
  maxHeight,
  children,
  alwaysShowChildren,
  onClick,
  onSelect,
  ...rest
}: SilkeListItemProps) => {
  const boxRef = useRef<HTMLButtonElement>(null);
  const hasSubItems = items && items.length > 0;
  const hasChildren = children && React.Children.count(children) > 0;
  const noContentRight = !icon && !children && !tag;

  const boxContent = (
    <>
      {icon && (
        <SilkeBox size="s" align="center" pad="xs" className={styles.icon}>
          {React.isValidElement(icon) || isString(icon) ? (
            <SilkeIcon icon={icon || 'error'} />
          ) : (
            <SilkeImage icon={icon as any} avatar="s" />
          )}
        </SilkeBox>
      )}
      <div className={styles.body}>
        <SilkeText size={size === 's' ? 'small' : 'base'} className={styles.label}>
          {label}
        </SilkeText>

        {subLabel && (
          <SilkeText size={size === 's' ? 'micro' : 'small'} className={styles.subLabel}>
            {subLabel}
          </SilkeText>
        )}
      </div>

      {tag && <SilkeTag {...tag} />}
      {hasSubItems && (
        <span className={styles.arrow}>
          <SilkeIcon icon="right" />
        </span>
      )}
      {children && <span className={styles.children}>{children}</span>}
    </>
  );

  const commonProps = {
    rounded: 'small' as const,
    gap: size === 's' ? 'xs' : 's',
    bgHover: 'surface-2',
    vPad: 'xs',
    vAlign: 'center',
    hPad: 'xs',
    height: size === 's' ? 's' : 'base',
    className: styles.item,
    'data-size': size,
    'data-active': active,
    'data-has-children': hasChildren,
    'data-no-icon': !icon,
    'data-pad-body-right': size !== 's' && noContentRight,
    'data-always-show-children': alwaysShowChildren,
    onClick: (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => {
      if (!hasSubItems) {
        onClick?.(e);
        onSelect?.();
      }
    },
    ...rest,
  };

  const linkProps = {
    tag: 'link',
    to: link,
    ...commonProps,
  } as BoxLinkProps;

  const buttonProps = {
    tag: 'button',
    ...commonProps,
  } as BoxButtonProps;

  return (
    <>
      {link ? (
        <SilkeBox ref={boxRef} {...linkProps}>
          {boxContent}
        </SilkeBox>
      ) : (
        <SilkeBox ref={boxRef} {...buttonProps}>
          {boxContent}
        </SilkeBox>
      )}

      {hasSubItems && (
        <SilkePopoverNative hint anchor={boxRef} placement="right-start" hideBackdrop offsetX={8}>
          <SilkeList items={items} gap={gap} maxHeight={maxHeight} onSelect={onSelect} />
        </SilkePopoverNative>
      )}
    </>
  );
};
