import React, { useContext, useMemo } from 'react';
import {
  ListBox as RACListBox,
  ListBoxItem as RACListBoxItem,
  ListBoxProps as RACListBoxProps,
  Collection,
  Header,
  Section,
  SectionProps,
  composeRenderProps,
} from 'react-aria-components';
import { composeTailwindRenderProps } from './tw-utils';
import { twMerge } from 'tailwind-merge';
import { Text } from './tw-text';
import { clsx } from '@trail-ui/shared-utils';
import { selectComboboxItem } from '@trail-ui/theme';
import { InternalListBoxContext } from '../listbox/listbox';
import { ListBoxSelectedIcon } from '../listbox/listbox-selected-icon';
import { ListBoxItemProps } from '../listbox';

interface ListBoxProps<T> extends Omit<RACListBoxProps<T>, 'layout' | 'orientation'> {}

export function ListBox<T extends object>({ children, ...props }: ListBoxProps<T>) {
  const ref = React.useRef<HTMLDivElement>(null);

  // // Fix not auto scroll to selected item
  // React.useEffect(() => {
  //   if (ref.current) {
  //     const selectedItem = ref.current.querySelector('[aria-selected=true]');
  //     if (selectedItem) {
  //       const timer = setTimeout(() => {
  //         selectedItem.scrollIntoView({
  //           block: 'nearest',
  //           behavior: 'smooth',
  //         });
  //       }, 50);

  //       return () => {
  //         clearTimeout(timer);
  //       };
  //     }
  //   }
  // }, []);

  return (
    <RACListBox
      {...props}
      className={composeTailwindRenderProps(props.className, 'outline-none')}
      ref={ref}
    >
      {children}
    </RACListBox>
  );
}

export function ListBoxItem(props: ListBoxItemProps) {
  const context = useContext(InternalListBoxContext);

  const {
    children,
    description,
    startContent,
    endContent,
    selectedIcon,
    className,
    classNames = context.itemClasses,
    ...otherProps
  } = props;

  const baseStyles = clsx(classNames?.base, className);
  const slots = useMemo(() => selectComboboxItem(), []);
  const textValue =
    props.textValue || (typeof props.children === 'string' ? props.children : undefined);

  return (
    <RACListBoxItem
      {...otherProps}
      textValue={textValue}
      className={slots.base({ class: baseStyles })}
    >
      {({ isSelected, isDisabled, selectionMode }) => {
        const selectedContent = () => {
          const defaultIcon = <ListBoxSelectedIcon isSelected={isSelected} />;

          if (typeof selectedIcon === 'function') {
            return selectedIcon({ icon: defaultIcon, isSelected, isDisabled });
          }

          if (selectedIcon) return selectedIcon;

          return defaultIcon;
        };

        return (
          <div aria-selected={isSelected} className="flex flex-1">
            {startContent}
            {description ? (
              <div className={slots.wrapper({ class: classNames?.wrapper })}>
                <Text slot="label" className={slots.title({ class: classNames?.title })}>
                  <>{children}</>
                </Text>
                <Text
                  slot="description"
                  className={slots.description({ class: classNames?.description })}
                >
                  {description}
                </Text>
              </div>
            ) : (
              <Text slot="label" className={slots.title({ class: classNames?.title })}>
                <>{children}</>
              </Text>
            )}
            {selectionMode !== 'none' && (
              <span
                aria-hidden="true"
                className={slots.selectedIcon({ class: classNames?.selectedIcon })}
              >
                {selectedContent()}
              </span>
            )}
            {endContent}
          </div>
        );
      }}
    </RACListBoxItem>
  );
}

export function DropdownItem({ destructive, ...props }: ListBoxItemProps & { destructive?: true }) {
  const textValue =
    props.textValue || (typeof props.children === 'string' ? props.children : undefined);

  return (
    <RACListBoxItem
      {...props}
      textValue={textValue}
      className={composeRenderProps(props.className, (className, { isDisabled, isFocused }) => {
        return twMerge([
          'group flex cursor-default select-none items-center gap-x-1 outline-none',
          'has-submenu:pe-0 px-1.5 py-2.5 sm:py-1.5',
          'text-base/6 sm:text-sm/6 [&:has(_[slot=description])_[slot=label]]:leading-5',
          '[&:not(:has([slot=description]))_[role=img]]:size-5',
          '[&:has([slot=description])_[role=img]]:size-7',
          '[&:has([slot=description])_[role=img]]:self-start',
          '[&:has([slot=description])_[role=img]]:mt-0.5',
          '[&:has([slot=description])_[role=img]]:me-0.5',
          isDisabled && 'opacity-50',
          isFocused && 'bg-hover',
          destructive && 'text-destructive',
          className,
        ]);
      })}
    >
      {composeRenderProps(props.children, (children, { isSelected }) => (
        <>
          <span className={twMerge('flex w-4 shrink-0 self-start', isSelected && 'mt-[5px]')}>
            {isSelected && <Check className="size-4" />}
          </span>
          <span
            className={twMerge(
              'flex min-w-0 flex-1 items-center gap-x-2',
              '[&>svg:not([class^=text-])]:text-muted',
              '[&>svg:not([class^=size-])]:size-4',
            )}
          >
            {children}
          </span>
        </>
      ))}
    </RACListBoxItem>
  );
}

export interface DropdownSectionProps<T> extends SectionProps<T> {
  title?: string;
}

export function DropdownSection<T extends object>({
  className,
  ...props
}: DropdownSectionProps<T>) {
  return (
    <Section
      className={twMerge(
        '[&:first-child]:-mt-[1px]',
        '[&:not(:first-child)]:my-1.5',
        '[&:not(:first-child)]:border-t-border/40 [&:not(:first-child)]:border-t',
        className,
      )}
    >
      <Header
        className={twMerge(
          'bg-background text-muted sticky z-10 truncate px-2 pt-2 text-xs/4',
          'top-[0px] -mx-[1px] rounded-md backdrop-blur-md',
        )}
      >
        {props.title}
      </Header>
      <Collection items={props.items}>{props.children}</Collection>
    </Section>
  );
}

function Check(props: JSX.IntrinsicElements['svg']) {
  return (
    <svg
      data-slot="icon-internal"
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 16 16"
      fill="currentColor"
      {...props}
    >
      <path
        fillRule="evenodd"
        d="M12.416 3.376a.75.75 0 0 1 .208 1.04l-5 7.5a.75.75 0 0 1-1.154.114l-3-3a.75.75 0 0 1 1.06-1.06l2.353 2.353 4.493-6.74a.75.75 0 0 1 1.04-.207Z"
        clipRule="evenodd"
      />
    </svg>
  );
}
