import { useState, useEffect, useCallback, Fragment } from "react";
import { useTranslation } from "next-i18next";
import { FiSearch } from "react-icons/fi";
import { SiDuckduckgo, SiMicrosoftbing, SiGoogle, SiBaidu, SiBrave } from "react-icons/si";
import { Listbox, Transition } from "@headlessui/react";
import classNames from "classnames";

import ContainerForm from "../widget/container_form";
import Raw from "../widget/raw";

export const searchProviders = {
  google: {
    name: "Google",
    url: "https://www.google.com/search?q=",
    icon: SiGoogle,
  },
  duckduckgo: {
    name: "DuckDuckGo",
    url: "https://duckduckgo.com/?q=",
    icon: SiDuckduckgo,
  },
  bing: {
    name: "Bing",
    url: "https://www.bing.com/search?q=",
    icon: SiMicrosoftbing,
  },
  baidu: {
    name: "Baidu",
    url: "https://www.baidu.com/s?wd=",
    icon: SiBaidu,
  },
  brave: {
    name: "Brave",
    url: "https://search.brave.com/search?q=",
    icon: SiBrave,
  },
  custom: {
    name: "Custom",
    url: false,
    icon: FiSearch,
  },
};

function getAvailableProviderIds(options) {
  if (options.provider && Array.isArray(options.provider)) {
    return Object.keys(searchProviders).filter((value) => options.provider.includes(value));
  }
  if (options.provider && searchProviders[options.provider]) {
    return [options.provider];
  }
  return null;
}

const localStorageKey = "search-name";

export function getStoredProvider() {
  if (typeof window !== "undefined") {
    const storedName = localStorage.getItem(localStorageKey);
    if (storedName) {
      return Object.values(searchProviders).find((el) => el.name === storedName);
    }
  }
  return null;
}

export default function Search({ options }) {
  const { t } = useTranslation();

  const availableProviderIds = getAvailableProviderIds(options);

  const [query, setQuery] = useState("");
  const [selectedProvider, setSelectedProvider] = useState(
    searchProviders[availableProviderIds[0] ?? searchProviders.google],
  );

  useEffect(() => {
    const storedProvider = getStoredProvider();
    let storedProviderKey = null;
    storedProviderKey = Object.keys(searchProviders).find((pkey) => searchProviders[pkey] === storedProvider);
    if (storedProvider && availableProviderIds.includes(storedProviderKey)) {
      setSelectedProvider(storedProvider);
    }
  }, [availableProviderIds]);

  const submitCallback = useCallback(
    (event) => {
      const q = encodeURIComponent(query);
      const { url } = selectedProvider;
      if (url) {
        window.open(`${url}${q}`, options.target || "_blank");
      } else {
        window.open(`${options.url}${q}`, options.target || "_blank");
      }

      event.preventDefault();
      event.target.reset();
      setQuery("");
    },
    [options.target, options.url, query, selectedProvider],
  );

  if (!availableProviderIds) {
    return null;
  }

  const onChangeProvider = (provider) => {
    setSelectedProvider(provider);
    localStorage.setItem(localStorageKey, provider.name);
  };

  return (
    <ContainerForm options={options} callback={submitCallback} additionalClassNames="grow information-widget-search">
      <Raw>
        <div className="flex-col relative h-8 my-4 min-w-fit">
          <div className="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none w-full text-theme-800 dark:text-white" />
          <input
            type="text"
            className="
            overflow-hidden w-full h-full rounded-md
            text-xs text-theme-900 dark:text-white
            placeholder-theme-900 dark:placeholder-white/80
            bg-white/50 dark:bg-white/10
            focus:ring-theme-500 dark:focus:ring-white/50
            focus:border-theme-500 dark:focus:border-white/50
            border border-theme-300 dark:border-theme-200/50"
            placeholder={t("search.placeholder")}
            onChange={(s) => setQuery(s.currentTarget.value)}
            required
            autoCapitalize="off"
            autoCorrect="off"
            autoComplete="off"
            // eslint-disable-next-line jsx-a11y/no-autofocus
            autoFocus={options.focus}
          />
          <Listbox
            as="div"
            value={selectedProvider}
            onChange={onChangeProvider}
            className="relative text-left"
            disabled={availableProviderIds?.length === 1}
          >
            <div>
              <Listbox.Button
                className="
          absolute right-0.5 bottom-0.5 rounded-r-md px-4 py-2 border-1
          text-white font-medium text-sm
          bg-theme-600/40 dark:bg-white/10
          focus:ring-theme-500 dark:focus:ring-white/50"
              >
                <selectedProvider.icon className="text-white w-3 h-3" />
                <span className="sr-only">{t("search.search")}</span>
              </Listbox.Button>
            </div>
            <Transition
              as={Fragment}
              enter="transition ease-out duration-100"
              enterFrom="transform opacity-0 scale-95"
              enterTo="transform opacity-100 scale-100"
              leave="transition ease-in duration-75"
              leaveFrom="transform opacity-100 scale-100"
              leaveTo="transform opacity-0 scale-95"
            >
              <Listbox.Options
                className="absolute right-0 z-10 mt-1 origin-top-right rounded-md
              bg-theme-100 dark:bg-theme-600 shadow-lg
              ring-1 ring-black ring-opacity-5 focus:outline-none"
              >
                <div className="flex flex-col">
                  {availableProviderIds.map((providerId) => {
                    const p = searchProviders[providerId];
                    return (
                      <Listbox.Option key={providerId} value={p} as={Fragment}>
                        {({ active }) => (
                          <li
                            className={classNames(
                              "rounded-md cursor-pointer",
                              active ? "bg-theme-600/10 dark:bg-white/10 dark:text-gray-900" : "dark:text-gray-100",
                            )}
                          >
                            <p.icon className="h-4 w-4 mx-4 my-2" />
                          </li>
                        )}
                      </Listbox.Option>
                    );
                  })}
                </div>
              </Listbox.Options>
            </Transition>
          </Listbox>
        </div>
      </Raw>
    </ContainerForm>
  );
}
