import { User as UserIcon, Users as TeamIcon } from 'lucide-react';
import { OptionProps, components, MultiValueGenericProps } from 'react-select';

import { Select } from '@@/form-components/ReactSelect';

type Option = { Type: 'user' | 'team'; Id: number; Name: string };

interface Props {
  value: Option[];
  onChange(value: readonly Option[]): void;
  options: Option[];
  isLoading?: boolean;
}

export function PorAccessManagementUsersSelector({
  options,
  value,
  onChange,
  isLoading,
}: Props) {
  return (
    <div className="form-group">
      <label
        className="col-sm-3 col-lg-2 control-label text-left"
        htmlFor="users-selector"
      >
        Select user(s) and/or team(s)
      </label>
      <div className="col-sm-9 col-lg-10">
        <Select
          isMulti
          getOptionLabel={(option) => option.Name}
          getOptionValue={(option) => `${option.Id}-${option.Type}`}
          options={options}
          value={value}
          closeMenuOnSelect={false}
          onChange={onChange}
          data-cy="component-selectUser"
          id="component-selectUser"
          inputId="users-selector"
          placeholder="Select one or more users and/or teams"
          components={{ MultiValueLabel, Option: OptionComponent }}
          isLoading={isLoading}
          loadingMessage={() => 'Loading users and teams...'}
          noOptionsMessage={() => 'No users or teams available.'}
        />
      </div>
    </div>
  );
}

function isOption(option: unknown): option is Option {
  return !!option && typeof option === 'object' && 'Type' in option;
}

function OptionComponent({ data, ...props }: OptionProps<Option, true>) {
  return (
    // eslint-disable-next-line react/jsx-props-no-spreading
    <components.Option data={data} {...props}>
      {isOption(data) && <Label option={data} />}
    </components.Option>
  );
}

function MultiValueLabel({
  data,
  ...props
}: MultiValueGenericProps<Option, true>) {
  return (
    // eslint-disable-next-line react/jsx-props-no-spreading
    <components.MultiValueLabel data={data} {...props}>
      {isOption(data) && <Label option={data} />}
    </components.MultiValueLabel>
  );
}

function Label({ option }: { option: Option }) {
  const Icon = option.Type === 'user' ? UserIcon : TeamIcon;

  return (
    <div className="flex items-center gap-1">
      <Icon />
      <span>{option.Name}</span>
    </div>
  );
}
