import React, { useState, useEffect } from 'react';
import Select, { type ControlProps, components } from 'react-select';
import { Globe } from 'lucide-react';
import useSWRImmutable from 'swr/immutable';
import { get } from '../utilities/fetcher.js';
import './RankSourceSelector.css';
import { useEffectEvent } from '../hooks/useEffectEvent.js';

export interface RankSource {
  id?: number;
  description?: string;
  isoLocale?: string;
}

interface SelectOption {
  value: string;
  label: string;
}

const RankSourceSelector = ({
  accountId,
  rankSource = {},
  setRankSource = (_) => {},
}: {
  accountId: string;
  rankSource?: RankSource;
  setRankSource?: (_: RankSource) => void;
}) => {
  const [selected, setSelected] = useState({ value: '', label: '' });

  const { data: rankSourcesData, isLoading } = useSWRImmutable<RankSource[]>(
    `/conductor/proxy/v3/${accountId}/rank-sources/content-guidance`,
    get,
  );

  const onRankSource = useEffectEvent((newRankSource) => {
    if (
      newRankSource.id !== rankSource.id ||
      newRankSource.description !== rankSource.description ||
      newRankSource.isoLocale !== rankSource.isoLocale
    ) {
      setRankSource(newRankSource);
    }
  });

  const rankSourcesById = React.useMemo(
    () =>
      rankSourcesData?.reduce((acc: { [key: string]: RankSource }, val: RankSource) => {
        const key = `${val.id}`;
        if (val.id && val.description && val.isoLocale) {
          acc[key] = {
            id: val.id,
            description: val.description,
            isoLocale: val.isoLocale,
          };
        }
        return acc;
      }, {}) || {},
    [rankSourcesData],
  );

  // Add missing description and isoLocale if this was loaded from a draft as only
  // the id is saved.
  useEffect(() => {
    if (
      !rankSourcesData?.length ||
      !rankSource.id ||
      (rankSource.description && rankSource.isoLocale)
    ) {
      return;
    }
    const match = rankSourcesData.find((rs) => rs.id === rankSource.id);
    if (match?.description && match?.isoLocale) {
      onRankSource({
        id: rankSource.id,
        description: match.description,
        isoLocale: match.isoLocale,
      });
    }
  }, [rankSourcesData, rankSource.id, rankSource.description, rankSource.isoLocale]);

  useEffect(() => {
    if (selected.value && rankSourcesById[selected.value]) {
      const selectedRankSource = rankSourcesById[selected.value];
      if (selectedRankSource) {
        onRankSource(selectedRankSource);
      }
    }
  }, [selected, rankSourcesById]);

  const selectOptions: SelectOption[] =
    rankSourcesData?.map((rankSource) => ({
      value: `${rankSource.id}`,
      label: rankSource.description ?? '',
    })) ?? [];

  let value: SelectOption | null = null;
  if (!isLoading && rankSource.id && rankSource.description) {
    value = {
      value: `${rankSource.id}`,
      label: rankSource.description,
    };
  }

  const SelectControl = (props: ControlProps<{ value: string; label: string }, false>) => (
    <components.Control {...props}>
      <Globe size={16} style={{ marginRight: '8px', color: '#6b7280' }} />
      {props.children}
    </components.Control>
  );

  return (
    <Select
      onChange={(newValue) => {
        setSelected(newValue as SelectOption);
      }}
      value={value}
      options={selectOptions}
      components={{
        Control: SelectControl,
      }}
      className="rank-source-selector"
      classNamePrefix="rank-source-selector"
      unstyled
      isSearchable={true}
      isMulti={false}
      isDisabled={isLoading}
      placeholder={isLoading ? 'Loading rank sources…' : 'Select rank source'}
      aria-label="Choose a rank source option"
    />
  );
};

export default RankSourceSelector;
