import React, { useState, useRef, useEffect, useContext } from "react";
import { connectSearchBox } from "react-instantsearch-dom";
import { useTranslation } from "react-i18next";
import styled from "styled-components";
import { sanitizeString, languageMap, onMouseDownOrTouchStart } from "../helpers";
import { autocomplete, getAlgoliaResults } from "@algolia/autocomplete-js";
import { createQuerySuggestionsPlugin } from "@algolia/autocomplete-plugin-query-suggestions";
import { createRedirectUrlPlugin } from "@algolia/autocomplete-plugin-redirect-url";
import { IndexContext } from "../context/IndexContext";
import { SiteContext } from "@arcteryx/components-contexts";
import { Body1Styles } from "@arcteryx/components-typography";

const SearchBoxWrapper = styled.div`
  flex: 1 1 auto;
  max-width: 100%;
  .aa-InputWrapperSuffix {
    display: none;
  }
  .aa-InputWrapperPrefix {
    order: 4;
  }
  .aa-Input {
    padding: 1rem;
    box-sizing: border-box;
    ${Body1Styles};
  }
  .aa-Form {
    border: 1px solid #707070;
    padding: 0;
    font-family: var(--font-helvetica);
    box-sizing: border-box;
    border-radius: 0;
    &:focus-within {
      border: 1px solid #707070;
      box-shadow: none;
    }
  }
  .aa-Label svg {
    color: var(--colour-copy);
  }
`;

const CustomSearchBox = ({ refine, currentRefinement, delay, autoFocus, searchPanelRef }) => {
  const { t } = useTranslation("container-search");
  const [value, setValue] = useState(currentRefinement);
  const timerIdRef = useRef(null);
  const { algoliaClient, setSuggestedSearch, environment, setSuggestedSearchContext, index } = useContext(IndexContext);
  const searchBoxRef = useRef(null);
  const { market, language } = useContext(SiteContext);

  const FACETS = ["gender", "collection", "categories", "materials", "colors.BaseColor", "review_value_rounded"];

  const onChangeDebounced = query => {
    const inputValue = sanitizeString(query);

    clearTimeout(timerIdRef.current);
    timerIdRef.current = setTimeout(() => refine(inputValue), delay);

    setValue(inputValue);
  };

  useEffect(() => {
    if (!searchBoxRef.current || !searchPanelRef.current) {
      return undefined;
    }
    const querySuggestionsPlugin = createQuerySuggestionsPlugin({
      searchClient: algoliaClient,
      indexName: `${environment}_arcteryx_product_${market}_${languageMap[language]}_query_suggestions`,
      getSearchParams: () => ({ hitsPerPage: 3 }),
      transformSource: ({ source }) => {
        return {
          ...source,
          templates: {
            ...source.templates,
            item({ item, components, html }) {
              return html`<div>${components.Highlight({ hit: item, attribute: "query", tagName: "strong" })}</div>`;
            },
          },
        };
      },
    });

    const redirectUrlPlugin = createRedirectUrlPlugin();

    const search = autocomplete({
      container: searchBoxRef.current,
      panelContainer: searchPanelRef.current,
      plugins: market === "leaf" ? [] : [querySuggestionsPlugin, redirectUrlPlugin],
      placeholder: t("Search"),
      insights: true,
      detachedMediaQuery: "none",
      initialState: {
        query: value || "",
      },
      onStateChange(props) {
        const { state, prevState, setContext } = props;
        if (prevState.query !== state.query) {
          // item is selected from query suggestions
          if(state.activeItemId !== null) {
            const querySuggestionCollection = state.collections?.find(
              item => item?.source?.sourceId === "querySuggestionsPlugin"
            );
            const suggestedItems = querySuggestionCollection?.items || [];
            setContext({
              searchTermSuggested: state.query,
              searchTermEntered: prevState.query,
              staticTerm: null,
              termCount: String(suggestedItems.length),
              terms: suggestedItems?.map(item => ({term: item.query})),
            });
          } else {
            setContext({
              searchTermSuggested: undefined,
              searchTermEntered: undefined,
              staticTerm: undefined,
              termCount: undefined,
              terms: undefined,
            });
          }
        }
        setSuggestedSearchContext(state.context);
      },
      getSources(props) {
        const { state } = props;
        return [
          {
            sourceId: "products",
            getItems({ query, setContext }) {
              return getAlgoliaResults({
                searchClient: algoliaClient,
                queries: [
                  {
                    indexName: index,
                    params: {
                      query,
                      hitsPerPage: 999,
                      facets: FACETS,
                    },
                  },
                ],
                transformResponse({ results }) {
                  setContext({
                    results,
                  });
                  onChangeDebounced(state.query);
                  return [];
                },
              });
            },
            templates: {
              item() {
                return null;
              },
            },
          },
        ];
      },
    });

    setSuggestedSearch(search);

    // set auto focus
    if (autoFocus) {
      const inputBox = searchBoxRef.current.querySelector("input");
      inputBox?.focus();
    }

    const handleOnMouseDownOrTouchStart = e =>
      onMouseDownOrTouchStart({
        event: e,
        searchBoxElem: searchBoxRef.current,
        searchPanelElem: searchPanelRef.current,
        setIsOpen: search.setIsOpen,
      });
    // Override autocomplete default click/touch event and keep search panel open
    // https://www.algolia.com/doc/ui-libraries/autocomplete/guides/creating-a-renderer/#mirroring-a-native-mobile-experience
    window.addEventListener("mousedown", handleOnMouseDownOrTouchStart);
    window.addEventListener("touchstart", handleOnMouseDownOrTouchStart);
    window.addEventListener("touchmove", handleOnMouseDownOrTouchStart);
    return () => {
      search.destroy();
    };
  }, []);

  return <SearchBoxWrapper ref={searchBoxRef} />;
};

export const SearchBox = connectSearchBox(CustomSearchBox);