import React, { useMemo, useState } from "react";
import classNames from "classnames";
import { ControlledProps, useDefaultValue } from "../form/controlled";
import { Omit } from "../_type";
import { DropdownProps, Dropdown, CommonDropdownProps } from "../dropdown";
import { RegionOption, RegionOptionContext } from "./RegionOption";
import { getPropsFromChildrenByType } from "../_util/get-props-from-children-by-type";
import { useConfig } from "../_util/config-context";
import { forwardRefWithStatics } from "../_util/forward-ref-with-statics";
import { useTranslation } from "../i18n";
import { RegionPanel } from "./RegionPanel";
import { callBoth } from "../_util/call-both";

export interface RegionSelectShortcutOptions {
  /**
   * 快捷选择标题
   * @default "最近访问" (已处理国际化)
   */
  title?: React.ReactNode;

  /**
   * 缓存 Key
   *
   * **缓存最近点击的项至 localStorage**
   * @since 2.7.2
   */
  cacheKey?: string;

  /**
   * 自定义快捷选择可选项
   */
  options?: string[];
}

export interface RegionSelectProps
  extends ControlledProps<string>,
    Omit<DropdownProps, "button" | "children" | "appearance" | "appearence"> {
  /**
   * 下拉内容，应该使用 `RegionPanel`
   */
  children?: React.ReactNode;

  /**
   * 在下拉按钮显示的额外信息
   */
  moreInfo?: React.ReactNode;

  /**
   * 是否禁用
   * @default false
   * @since 2.4.1
   */
  disabled?: boolean;

  /**
   * 快捷选择（最近访问）区域配置
   *
   * 选项设置方式：
   * - 设置 `cacheKey` 使用默认缓存方式记录最近访问选项
   * - 设置 `options` 自定义该区域可选项
   *
   * @since 2.5.0
   */
  shortcut?: RegionSelectShortcutOptions;
}

export const RegionSelect = forwardRefWithStatics(
  function RegionSelect(
    props: RegionSelectProps,
    ref: React.Ref<HTMLDivElement>
  ) {
    const t = useTranslation();
    const { classPrefix } = useConfig();
    const [open, setOpen] = useState(false);
    // eslint-disable-next-line react/destructuring-assignment
    const options = useMemo(
      () => getPropsFromChildrenByType(props.children, RegionOption),
      [props.children]
    );
    const columns = useMemo(
      () => getPropsFromChildrenByType(props.children, RegionPanel.Column),
      [props.children]
    );

    const {
      value,
      onChange,
      moreInfo,
      children,
      disabled,
      shortcut,
      ...dropdownProps
    } = useDefaultValue(props, options[0]?.value);

    const shortcutContent = useMemo(() => {
      if (shortcut?.cacheKey) {
        let shortcutOptions = [];
        try {
          shortcutOptions = JSON.parse(
            localStorage.getItem(shortcut.cacheKey) || "[]"
          );
        } catch (_) {
          // ignore
        }

        return {
          title: t.recentlyVisited,
          ...shortcut,
          options: shortcutOptions
            .map(value => options.find(x => x && x.value === value))
            .filter(Boolean)
            .slice(0, columns?.length || 1),
        };
      }

      if (shortcut?.options) {
        return {
          title: t.recentlyVisited,
          ...shortcut,
          options: shortcut.options
            .map(value => options.find(x => x && x.value === value))
            .filter(Boolean),
        };
      }
      return null;
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [columns, options, shortcut, t.recentlyVisited, open]);

    const selectedOption =
      options.find(x => x && x.value === value) || options[0];

    return (
      <Dropdown
        ref={ref}
        {...dropdownProps}
        boxAdaptable
        appearance="button"
        className={classNames(
          `${classPrefix}-dropdown--region-select`,
          dropdownProps.className
        )}
        disabled={disabled}
        clickClose={false}
        onOpenChange={callBoth(dropdownProps.onOpenChange, open =>
          setOpen(open)
        )}
        button={
          <>
            {selectedOption && <RegionOption {...selectedOption} />}
            {moreInfo && (
              <div className={`${classPrefix}-region__more`}>{moreInfo}</div>
            )}
          </>
        }
      >
        {close => (
          <RegionOptionContext.Provider
            value={{
              inject(props) {
                return {
                  ...props,
                  selected: value === props.value,
                  onClick(event) {
                    if (typeof props.onClick === "function") {
                      props.onClick(event);
                    }
                    if (event.isDefaultPrevented()) {
                      return;
                    }
                    onChange(props.value, { event });
                    close();

                    if (
                      shortcut?.cacheKey &&
                      typeof localStorage !== "undefined"
                    ) {
                      let shortcutOptions = [];
                      try {
                        shortcutOptions = JSON.parse(
                          localStorage.getItem(shortcut.cacheKey) || "[]"
                        );

                        localStorage.setItem(
                          shortcut.cacheKey,
                          JSON.stringify(
                            [
                              props.value,
                              ...shortcutOptions.filter(i => i !== props.value),
                            ].slice(0, 12)
                          )
                        );
                      } catch (_) {
                        // ignore
                      }
                    }
                  },
                };
              },
              shortcut: shortcutContent,
            }}
          >
            {children}
          </RegionOptionContext.Provider>
        )}
      </Dropdown>
    );
  },
  {
    defaultLabelAlign: "middle",
  }
);

RegionSelect.displayName = "RegionSelect";
