/* eslint-disable @typescript-eslint/no-explicit-any */
import { useCallback, useEffect, useRef, useState } from "react";
import debounce from "lodash/debounce";
import GlobalSearchView from "./GlobalSearchView";

export type GlobalSearchProps = {
  uiElementGroupData: Record<string, any>;
  visible: boolean;
  disabled: boolean;
  config: { uiElementGroupId: string };
  onModelUpdate: (
    callBack: ((args: any) => void) | null,
    fieldName: string,
    value: any
  ) => void;
};

const GlobalSearch = (props: GlobalSearchProps) => {
  const [searchValue, setSearchValue] = useState("");
  const isLocalChange = useRef(false);

  // If appliedQuery has value but filterQuery doesn't, update filterQuery
  useEffect(() => {
    if (
      props.uiElementGroupData?.globalSearch?.appliedQuery &&
      !props.uiElementGroupData?.globalSearch?.filterQuery
    ) {
      const updatedUiElementGroupData = {
        ...props.uiElementGroupData,
        globalSearch: {
          ...props.uiElementGroupData.globalSearch,
          filterQuery: props.uiElementGroupData.globalSearch.appliedQuery,
        },
      };
      props.onModelUpdate(
        null,
        props.config.uiElementGroupId,
        updatedUiElementGroupData
      );
    }
  }, [props.uiElementGroupData?.globalSearch?.appliedQuery]);

  useEffect(() => {
    if (isLocalChange.current) {
      isLocalChange.current = false;
      return;
    }
    setSearchValue(props.uiElementGroupData?.globalSearch?.filterQuery ?? "");
  }, [props.uiElementGroupData?.globalSearch?.filterQuery]);

  const onSearch = () => {
    if (props.uiElementGroupData.globalSearch.filterQuery) {
      const updatedUiElementGroupData = {
        ...props.uiElementGroupData,
        globalSearch: {
          ...props.uiElementGroupData.globalSearch,
          appliedQuery: props.uiElementGroupData.globalSearch.filterQuery,
        },
        pagination: { ...props.uiElementGroupData.pagination, skip: 0 },
      };

      props.onModelUpdate(
        null,
        props.config.uiElementGroupId,
        updatedUiElementGroupData
      );
    }
  };

  const onClearSearch = () => {
    const updatedUiElementGroupData = {
      ...props.uiElementGroupData,
      globalSearch: {
        ...props.uiElementGroupData.globalSearch,
        filterQuery: "",
        appliedQuery: "",
      },
      pagination: { ...props.uiElementGroupData.pagination, skip: 0 },
    };
    props.onModelUpdate(
      null,
      props.config.uiElementGroupId,
      updatedUiElementGroupData
    );
  };

  const debouncedModelUpdate = useCallback(
    debounce((searchKey: string) => {
      const updatedUiElementGroupData = {
        ...latestUiElementGroupDataRef.current,
        globalSearch: {
          ...latestUiElementGroupDataRef.current.globalSearch,
          filterQuery: searchKey,
        },
      };
      props.onModelUpdate(
        null,
        props.config.uiElementGroupId,
        updatedUiElementGroupData,
      );
    }, 300),
    [props.config.uiElementGroupId],
  );

  const latestUiElementGroupDataRef = useRef(props.uiElementGroupData);
  useEffect(() => {
    latestUiElementGroupDataRef.current = props.uiElementGroupData;
  }, [props.uiElementGroupData]);

  const onSearchChange = (searchKey: string | undefined) => {
    isLocalChange.current = true;
    setSearchValue(searchKey ?? "");
    if (props.uiElementGroupData.globalSearch.filterQuery && !searchKey) {
      debouncedModelUpdate.cancel();
      onClearSearch();
    } else if (searchKey) {
      debouncedModelUpdate(searchKey);
    }
  };

  return props.visible ? (
    <GlobalSearchView
      disabled={props.disabled}
      value={searchValue}
      onSearchChange={onSearchChange}
      onClearSearch={onClearSearch}
      onSearch={onSearch}
    />
  ) : (
    <></>
  );
};
export default GlobalSearch;
