'use client'
import { ReactElement, useState } from 'react'
import {
  Button,
  type Key,
  ListBox,
  ListBoxItem,
  Popover,
  Select as ReactAriaSelect,
  SelectValue,
} from 'react-aria-components'

import SelectChevron from './SelectChevron'

import styles from './select.module.css'
import Body from '../Body'
import { InputLabel } from '../InputLabel'

interface SelectProps extends Omit<
  React.SelectHTMLAttributes<HTMLSelectElement>,
  'onSelect'
> {
  defaultSelectedKey?: Key
  items: { label: string; value: Key }[]
  label: string
  name: string
  onSelect: (key: Key) => void
  value?: string | number
  maxHeight?: number
  showRadioButton?: boolean
  discreet?: boolean
  isNestedInModal?: boolean
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  optionsIcon?: ReactElement<any>
}

type SelectPortalContainer = HTMLDivElement | undefined
type SelectPortalContainerArgs = HTMLDivElement | null

const DELIMITER = ':'

/**
 * @deprecated Do not use.
 */
export default function Select({
  className = '',
  'aria-label': ariaLabel,
  defaultSelectedKey,
  items,
  label,
  name,
  onSelect,
  disabled,
  required = false,
  tabIndex,
  value,
  maxHeight,
  showRadioButton = false,
  discreet = false,
  isNestedInModal = false,
  optionsIcon,
}: SelectProps) {
  const [rootDiv, setRootDiv] = useState<SelectPortalContainer>(undefined)
  const setOverflowVisible = useSetOverflowVisibleOnRA(isNestedInModal)

  function setRef(node: SelectPortalContainerArgs) {
    if (node) {
      setRootDiv(node)
    }
  }

  function handleOnSelect(key: Key | null) {
    if (key !== null) {
      onSelect(key)
    }
  }

  let chevronProps = {}

  if (discreet) {
    chevronProps = { color: 'baseButtonTextOnFillNormal' }
  } else if (disabled) {
    chevronProps = { color: 'disabled' }
  }

  return (
    <div className={`${styles.container} ${className}`} ref={setRef}>
      <ReactAriaSelect
        aria-label={ariaLabel}
        className={`${styles.select} ${discreet ? styles.discreet : ''} select-container`}
        defaultSelectedKey={defaultSelectedKey}
        name={name}
        onSelectionChange={handleOnSelect}
        selectedKey={value as Key}
        onOpenChange={setOverflowVisible}
        isDisabled={disabled}
      >
        <Body asChild fontOnly>
          <Button
            className={`${styles.input} select-button`}
            data-testid={name}
          >
            <SelectValue tabIndex={tabIndex}>
              {({ selectedText }) => (
                <>
                  <InputLabel
                    required={required}
                    size={discreet ? 'discreet' : 'regular'}
                  >
                    {label}
                    {discreet && DELIMITER}
                  </InputLabel>
                  {selectedText && (
                    <Body className={optionsIcon ? styles.iconLabel : ''}>
                      {optionsIcon ? optionsIcon : null}
                      {selectedText}
                    </Body>
                  )}
                </>
              )}
            </SelectValue>
            <SelectChevron {...chevronProps} />
          </Button>
        </Body>
        <Body asChild fontOnly>
          <Popover
            className={styles.popover}
            placement="bottom"
            shouldFlip={false}
            /**
             * react-aria uses portals to render Popover in body
             * unless otherwise specified. We need it to be contained
             * by this component to both access css variables assigned
             * on the container as well as to not overflow it at any time.
             */
            UNSTABLE_portalContainer={rootDiv}
            maxHeight={maxHeight}
          >
            <ListBox className={styles.listBox}>
              {items.map((item) => (
                <ListBoxItem
                  aria-label={item.label}
                  className={`${styles.listBoxItem} ${showRadioButton && styles.showRadioButton} ${optionsIcon && styles.iconLabel}`}
                  id={item.value}
                  key={`${item.value}_${item.label}`}
                  data-testid={item.label}
                >
                  {optionsIcon}
                  {item.label}
                </ListBoxItem>
              ))}
            </ListBox>
          </Popover>
        </Body>
      </ReactAriaSelect>
    </div>
  )
}

function useSetOverflowVisibleOnRA(isNestedInModal?: boolean) {
  function setOverflowVisible(isOpen: boolean) {
    if (isOpen) {
      document.body.style.overflow = 'visible'
    } else if (!isNestedInModal) {
      document.body.style.overflow = ''
    }
  }

  return setOverflowVisible
}
