import React, { useEffect, useState } from 'react';
import { BeatLoader } from 'react-spinners';
import styled from 'styled-components';
import { v4 as uuidv4 } from 'uuid';
import { uiColors } from '../constants/uiColors';

export interface IAsyncDropdownOptionsProps {
  id: number;
  value: string;
  option: string | JSX.Element;
}

export interface IAsyncDropdownProps {
  options: IAsyncDropdownOptionsProps[];
  width?: string;
  onChange: (value: string) => void;
  defaultValue?: string;
  opensUp?: boolean;
}

export const AsyncDropdown: React.FC<IAsyncDropdownProps> = ({
  options,
  width,
  onChange,
  defaultValue,
  opensUp = false,
}) => {
  const dropdownId = uuidv4();

  const [selectedValue, setSelectedValue] = useState<string>(
    defaultValue || options?.[0]?.value
  );
  const [selectedOption, setSelectedOption] = useState<string | JSX.Element>(
    options?.find(option => option.value === defaultValue)?.option ||
      options?.[0]?.option
  );
  const [opened, setOpened] = useState<boolean>(false);

  useEffect(() => {
    if (defaultValue) {
      setSelectedValue(defaultValue);
      setSelectedOption(
        //@ts-ignore
        options?.find(option => option.value === defaultValue)?.option
      );
    } else if (options?.length > 0) {
      setSelectedValue(options[0].value);
      setSelectedOption(options[0].option);
    }
  }, [options, defaultValue]);

  const handleSelection = (value: string, option: string | JSX.Element) => {
    if (value !== selectedValue) {
      setSelectedValue(value);
      setSelectedOption(option);
      onChange(value);
    }
  };

  return (
    <Container onMouseLeave={() => setOpened(false)} width={width}>
      <DropdownSelect
        id={`dropdown-${dropdownId}`}
        className="rpgui-dropdown-imp rpgui-dropdown-imp-header"
        onPointerUp={() => setOpened(prev => !prev)}
      >
        <DropdownDisplay>
          <DropdownLabel>▼</DropdownLabel> {selectedOption}
          {!options.length && <BeatLoader size={4} color={uiColors.white} />}
        </DropdownDisplay>
      </DropdownSelect>

      <DropdownOptions
        className="rpgui-dropdown-imp"
        opened={opened}
        opensUp={opensUp}
      >
        {options?.map(option => (
          <li
            key={option.id}
            onPointerUp={() => {
              handleSelection(option.value, option.option);
              setOpened(false);
            }}
          >
            {option.option}
          </li>
        ))}
      </DropdownOptions>
    </Container>
  );
};

const DropdownDisplay = styled.span`
  display: flex;
  flex-wrap: wrap;
  justify-content: start;
  align-items: center;
`;

const DropdownLabel = styled.label`
  margin-right: 0.5rem;
`;

const Container = styled.div<{ width: string | undefined }>`
  position: relative;
  width: ${props => props.width || '100%'};
`;

const DropdownSelect = styled.p`
  width: 100%;
  box-sizing: border-box;

  label {
    display: inline-block;
    transform: translateY(-2px);
  }
`;

const DropdownOptions = styled.ul<{
  opened: boolean;
  opensUp: boolean;
}>`
  position: absolute;
  width: 100%;
  max-height: 300px;
  overflow-y: auto;
  display: ${props => (props.opened ? 'block' : 'none')};
  box-sizing: border-box;
  bottom: ${props => (props.opensUp ? '100%' : 'auto')};
  top: ${props => (props.opensUp ? 'auto' : '100%')};
  margin: 0;
  padding: 0;

  @media (max-width: 768px) {
    padding: 8px 0;
  }
`;
