/* eslint-disable @typescript-eslint/no-unused-vars */
import React, { KeyboardEvent, MouseEvent, ReactNode, forwardRef } from "react";
import Portal from "@reach/portal";
import classNames from "classnames";
import { bem } from "../../utilities/bem";
import { Box } from "../Box";
import { CloseButton } from "../CloseButton";
import { Icon, ICON_TYPE } from "../Icon";
import { Token } from "../Token";
// import { Portal } from "../Portal";
import { OptionInterface } from "./useSelect";

export const cn = "Combobox";
export const selectInputCn = bem(cn, { e: "input" });
export const surfaceClassName = classNames([
  bem(cn, { e: "surface" }),
  `${bem("TextInput")}`,
  `${bem("TextInput", { m: "default" })}`,
]);
export const surfaceMultiClassName = bem(cn, { e: "surface", m: "multi" });
export const defaultPopperModifiers = {
  offset: {
    offset: "0, 4px",
  },
  preventOverflow: {
    enabled: false,
  },
  hide: {
    enabled: false,
  },
};

export interface ComboboxSharedProps {
  options: OptionInterface[];
  defaultValue?: OptionInterface;
  placeholder?: string;
  isCreatable?: boolean;
  isClearable?: boolean;
  isSearchable?: boolean;
  onCreate?: (v: OptionInterface) => any;
  onChange?: (v: OptionInterface | OptionInterface[]) => any;
  // getOptionLabel?: (v: string) => string;
  // getOptionValue?: (v: string) => string;
  // formatOptionLabel?: (option: DropdownOption) => ReactNode;
  className?: string;
  disabled?: boolean;
}

interface NoOptionsProps {
  canCreate: boolean;
  searchValue: string;
  create: (v: OptionInterface) => any;
}

interface OptionProps {
  onClick: () => void;
  children: ReactNode;
  isHover: boolean;
  isSelected: boolean;
  hover?: () => void;
  id?: string;
}

export const Option = ({
  children,
  onClick,
  isHover = false,
  isSelected = false,
  hover = () => {},
  id,
}: OptionProps) => {
  return (
    <Box
      onClick={onClick}
      onMouseEnter={() => hover()}
      className={classNames([
        bem(cn, { e: "option" }),
        isHover && bem(cn, { e: "option", m: "isHover" }),
        isSelected && bem(cn, { e: "option", m: "isSelected" }),
      ])}
      id={id}
      aria-selected={isSelected}
      role="option"
    >
      {children}
    </Box>
  );
};

export const NoOptions = ({
  canCreate,
  searchValue,
  create,
}: NoOptionsProps) => {
  return canCreate ? (
    <Option
      onClick={() => create({ value: searchValue })}
      id={searchValue}
      isHover
      isSelected
    >
      Create &quot;{searchValue}&quot;
    </Option>
  ) : (
    <Box className={bem(cn, { e: "noOptions" })}>No options</Box>
  );
};

interface ListboxProps {
  children: ReactNode;
  top: number;
  left: number;
  width?: string | number;
}

export const Listbox = ({
  children,
  top = 0,
  left = 0,
  width = "100%",
}: ListboxProps) => {
  return (
    <Portal>
      <Box
        role="listbox"
        style={{ position: "absolute", top, left, width }}
        className={bem(cn, { e: "listbox" })}
      >
        {children}
      </Box>
    </Portal>
  );
};

interface TagProps {
  children: ReactNode;
  onRemove: () => void;
}

export const Tag = ({ children, onRemove }: TagProps) => {
  const onClick = (event: MouseEvent<HTMLButtonElement>): void => {
    event.stopPropagation();
    onRemove();
  };

  return (
    <Token className={bem(cn, { e: "tag" })} onRemove={onClick} removable>
      {children}
    </Token>
  );
};

interface ContainerProps {
  isOpen: boolean;
  children: ReactNode;
  close: () => void;
  selectedId?: string;
  className?: string;
  disabled?: boolean;
  onKeyDown?: (event: KeyboardEvent) => void;
}

export const Container = forwardRef(
  (
    {
      children,
      selectedId,
      className,
      disabled,
      onKeyDown = () => {},
      close,
      isOpen,
    }: ContainerProps,
    ref,
  ) => {
    return (
      <Box
        ref={ref}
        className={classNames([
          bem(cn),
          disabled && bem(cn, { m: "disabled" }),
          className,
        ])}
        aria-activedescendant={selectedId}
        role="combobox"
        onKeyDown={onKeyDown}
        tabIndex={0}
      >
        {children}
      </Box>
    );
  },
);

export const Arrow = () => (
  <Icon className="text-gray-700" icon={ICON_TYPE.CARET_DOWN} />
);

interface ClearButtonProps {
  canClear: boolean;
  clear: () => void;
}

export const ClearButton = ({ canClear, clear }: ClearButtonProps) => {
  const onClick = (event: MouseEvent<HTMLButtonElement>): void => {
    event.stopPropagation();
    clear();
  };

  return canClear ? <CloseButton onClick={onClick} /> : null;
};
