import { memo, useCallback } from 'react';
import classNames from 'classnames';

import type { WithSpacingProps } from '~/src/lib/hocs/withSpacing';
import type { ReactNode, SelectHTMLAttributes } from 'react';

import Box from '../Box';

export interface SelectProps
  extends WithSpacingProps,
    Pick<
      SelectHTMLAttributes<HTMLSelectElement>,
      'name' | 'value' | 'defaultValue'
    > {
  title: string;
  testId?: string;

  items: {
    id: string;
    text: string;
  }[];

  onChange: (value: string) => void;
  withFocusStyle?: boolean;
  children?: ReactNode;
}

/**
 * Use for small/subtle select pickers. Uses native html select under the hood.
 * For everything else use Select2.
 */
const Select = memo<SelectProps>(
  ({
    items,
    value,
    defaultValue,
    children,
    onChange,
    title,
    testId,
    name,
    withFocusStyle = true,
    ...props
  }) => {
    const onSelectChange = useCallback((event) => {
      onChange(event.target.value);
    }, []);

    return (
      <Box
        positionRelative
        style={{ overflow: 'hidden' }}
        data-testid={testId}
        pointerEvents="none"
        padding="0.1rem 0"
        {...props}
      >
        <select
          className={classNames({ withFocusStyle })}
          onChange={onSelectChange}
          defaultValue={defaultValue}
          // add value prop only when defined to avoid react 'controlled' inputs
          // when we actually want to use defaultValue/uncontrolled
          {...(value !== undefined ? { value } : {})}
          name={name}
          title={title}
          style={{
            fontSize: 16,
            opacity: 0,
            position: 'absolute',
            left: 0,
            top: 0,
            width: '100%',
            height: '100%',
            cursor: 'pointer',
            pointerEvents: 'all',
          }}
        >
          {items.map(({ id, text }) => (
            <option key={id} value={id}>
              {text}
            </option>
          ))}
        </select>
        {children}
        <style jsx>{`
          /* subtle glow when focused via keyboard */
          select.withFocusStyle:focus-visible ~ :global(*) {
            filter: drop-shadow(0px 1px 8px white);
          }
        `}</style>
      </Box>
    );
  }
);

export default Select;
