import {SelectProps} from "@atlaskit/forge-react-types";
import {invoke} from "@forge/bridge";
import {Select, Spinner} from "@forge/react";
import React, {useEffect, useState} from "react";
import ForgeUI from '@forge/ui';
import {useDebounce} from "../../hooks/useDebounce";
import {Space} from "../../lib/confluence/types";

export interface PageSelectProps extends SelectProps {
  spaceId?: string;
}

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

export default function PageSelect(props: PageSelectProps) {
  const { defaultValue, isMulti, onChange, spaceId } = props;
  const [initialized, setInitialized] = useState(false);
  const [spaceKey, setSpaceKey] = useState<string>();
  const [keyword, setKeyword] = useState('');
  const debouncedKeyword = useDebounce<string>(keyword, 250);
  const [isLoading, setIsLoading] = useState(false);
  const [options, setOptions] = useState<SelectOption[]>([]);

  useEffect(() => {
    if (defaultValue) {
      invoke('confluence.getPageById', {
        pageId: defaultValue
      }).then((page: any) => {
        setOptions([
          {
            label: page.title,
            value: page.id
          }
        ]);
        setInitialized(true);
      })
    } else {
      setInitialized(true);
    }
  }, []);

  useEffect(() => {
    if (spaceId) {
      setIsLoading(true);
      invoke<Space>('confluence.getSpaceById', {
        spaceId: spaceId
      }).then((space) => {
        setSpaceKey(space.key);
      });
    }
  }, [spaceId]);

  // Get the related pages by space key and keyword.
  useEffect(() => {
    if (spaceKey) {
      let cql = `space.key="${spaceKey}"`;
      if (debouncedKeyword) {
        cql += ` AND title~"${debouncedKeyword}"`
      }

      console.log(`Invoke confluence.search with params (cql: '${cql}', limit: 5)`);
      setIsLoading(true);
      invoke<any>('confluence.search', {
        cql: cql,
        limit: 5
      }).then((res) => {
        // Option list.
        const options = (res.results || [])
          .filter((item: any) => Boolean(item.content))
          .map((item: any) => {
            return {
              label: item.content?.title,
              value: item.content?.id
            }
          });

        setOptions(options);
      }).finally(() => {
        setIsLoading(false);
      });
    } else {
      setIsLoading(false);
    }
  }, [spaceKey, debouncedKeyword]);

  return <>
    {
      initialized ?
      <Select
        isDisabled={!!spaceKey}
        isSearchable={true}
        isLoading={isLoading}
        appearance="default"
        spacing="compact"
        options={options}
        {...props}
        onInputChange={(inputValue: string) => {
          setKeyword(inputValue);
        }}
        defaultValue={
          isMulti ?
          options?.filter((o: any) => defaultValue?.includes(o.value)) :
          options?.find((o: any) => o.value === defaultValue)
        }
        onChange={(selectedOption: any, e) => {
          if (onChange) {
            if (isMulti) {
              onChange(selectedOption.map((o: any) => {
              return o.value
            }), e)
          } else {
            onChange(selectedOption.value, e)
          }
        }
      }}
      /> :
      <Spinner/>
    }
  </>;
}