import React, { useEffect, useId, useState } from 'react';
import { AsyncPaginate } from 'react-select-async-paginate';
import axios from 'axios';

const getOptionLabel = (item: any, showField?: string) => {
  if (!item) {
    return '';
  }

  if (showField && item[showField]) {
    return item[showField];
  }

  return (
    item.label ||
    item.name ||
    item.firstName ||
    item.email ||
    item.action ||
    item.title ||
    item.request_code ||
    item.reservation_code ||
    item.file_name ||
    item.summary ||
    item.reference ||
    item.id ||
    ''
  );
};

const toSelectOption = (item: any, showField?: string) => {
  if (!item) {
    return null;
  }

  const value = item.value || item.id;

  if (!value) {
    return null;
  }

  return {
    value,
    label: getOptionLabel(item, showField),
  };
};

export const SelectFieldMany = ({ options, field, form, itemRef, showField }) => {
  const [value, setValue] = useState([]);
  const PAGE_SIZE = 100;

  useEffect(() => {
    if (!Array.isArray(field?.value) || field.value.length === 0) {
      setValue([]);
      return;
    }

    const nextValue = field.value
      .map((item) => {
        if (typeof item === 'string') {
          const matchingOption = Array.isArray(options)
            ? options.find((option) => option?.id === item || option?.value === item)
            : null;

          return {
            value: item,
            label: getOptionLabel(matchingOption, showField) || item,
          };
        }

        return toSelectOption(item, showField);
      })
      .filter(Boolean);

    setValue(nextValue);

    const normalizedIds = field.value
      .map((item) => {
        if (typeof item === 'string') {
          return item;
        }

        return item?.id || item?.value || null;
      })
      .filter(Boolean);

    const shouldNormalizeFieldValue = field.value.some((item) => typeof item !== 'string');

    if (shouldNormalizeFieldValue) {
      form.setFieldValue(field.name, normalizedIds);
    }
  }, [field?.name, field?.value, form, options, showField]);

  const mapResponseToValuesAndLabels = (data) => ({
    value: data.id,
    label: data.label,
  });

  const handleChange = (data: any) => {
    const nextValue = Array.isArray(data) ? data : [];

    setValue(nextValue);
    form.setFieldValue(
      field.name,
      nextValue.map((item) => item?.value).filter(Boolean),
    );
  };

  async function callApi(inputValue: string, loadedOptions: any[]) {
    const path = `/${itemRef}/autocomplete?limit=${PAGE_SIZE}&offset=${loadedOptions.length}${inputValue ? `&query=${inputValue}` : ''}`;
    const { data } = await axios(path);
    return {
      options: data.map(mapResponseToValuesAndLabels),
      hasMore: data.length === PAGE_SIZE,
    };
  }

  return (
    <AsyncPaginate
      classNames={{
        control: () => 'px-1 py-2',
      }}
      classNamePrefix='react-select'
      instanceId={useId()}
      value={value}
      isMulti
      debounceTimeout={1000}
      loadOptions={callApi}
      onChange={handleChange}
      defaultOptions
      isClearable
    />
  );
};
