import HncyModal from '@/components/HncyModal';
import { useBoolean } from 'ahooks';
import { Flex } from 'antd';
import React, {
  forwardRef,
  useEffect,
  useImperativeHandle,
  useMemo,
  useState,
} from 'react';
import styles from './index.less';
import Registry, { ModalKey } from './registry';
import type {
  GlobalModalConfig,
  GlobalModalPrideAction,
  ModalStackType,
} from './type';

let modalIndex = 0;

/** 获取弹窗内容 */
const getModalElement = (modalKey: ModalKey) => {
  if (modalKey in Registry) {
    return Registry[modalKey];
  } else {
    throw new Error(`Modal ${modalKey} not found`);
  }
};

/** @module 全居弹窗服务 */
const GlobalModalServices: React.ForwardRefRenderFunction<
  GlobalModalPrideAction,
  any
> = (_, ref) => {
  const [modalStack, setModalStack] = useState<ModalStackType[]>([]);

  const [open, { setFalse, setTrue }] = useBoolean(false);

  useEffect(() => {
    if (modalStack.length === 0) {
      setFalse();
    } else {
      setTrue();
    }
  }, [modalStack]);

  /** @see GlobalModalServicesModalMethods.push */
  const push = (modalKey: ModalKey, config?: GlobalModalConfig) => {
    /** 生成弹窗id */
    const modalId = `modal_${modalIndex++}`;
    const { defaultConfig, defaultProps, render } = getModalElement(modalKey);
    const newConfig = { ...defaultConfig, ...config };
    const newProps = { ...defaultProps, ...(config?.props ?? {}) };
    let modalElement: JSX.Element | undefined;
    if (newConfig.keepalive) {
      /**
       * 保存在栈中，不重复渲染。此实现无法避免组件的卸载与状态保持，仅节约重复渲染时间
       * 暂存 @see https://github.com/CJY0208/react-activation
       * 等待有时间实现keepalive功能
       * */
      modalElement = render(newProps);
    }
    const newModalStack = {
      ...newConfig,
      modalId,
      props: newProps,
      modalKey,
      modalElement,
      render,
    };
    setModalStack((pre) => [...pre, newModalStack]);
    return modalId;
  };
  /** @see GlobalModalServicesModalMethods.go */
  const go = (modalId: string) => {
    const index = modalStack.findIndex((item) => item.modalId === modalId);
    if (index === -1) {
      throw new Error('modal not found');
    } else {
      setModalStack((pre) => pre.filter((_, i) => i <= index));
    }
  };

  /** @see GlobalModalServicesModalMethods.remove */
  const remove = (id: string) => {
    setModalStack((prev) => {
      return prev.filter((item) => item.modalId !== id);
    });
  };
  /** @see GlobalModalServicesModalMethods.setOptions */
  const setOptionsById = (id: string, config: any) => {
    setModalStack((prev) => {
      return prev.map((item) => {
        if (item.modalId === id) {
          return {
            ...item,
            ...config,
          };
        }
        return item;
      });
    });
  };
  /** 设置options */
  const setOptions = (options: Partial<GlobalModalConfig>) => {
    setModalStack((prev) => {
      return prev.map((item, index) => {
        if (index === prev.length - 1) {
          return {
            ...item,
            ...options,
          };
        }
        return item;
      });
    });
  };

  useImperativeHandle(ref, () => ({
    close,
    setOptions,
    setOptionsById,
    push,
    goBack,
    remove,
    go,
    clear,
  }));

  /** @see GlobalModalServicesModalMethods.clear */
  const clear = () => {
    setModalStack([]);
  };

  /**
   * @description modal返回
   *  */
  const goBack = () => {
    setModalStack((prev) => {
      return prev.slice(0, prev.length - 1);
    });
  };

  /** 获取当前弹窗的内容 */
  const renderModal = () => {
    const curModal = modalStack.at(-1);
    /** 避免重复渲染 */
    if (curModal?.modalElement) {
      return curModal.modalElement;
    }

    return curModal?.render(curModal.props);
  };

  const modalOptions = useMemo(() => {
    return modalStack.at(-1) ?? ({} as ModalStackType);
  }, [modalStack]);

  /** 标题渲染 */
  const titleRender = () => {
    const { headerLeft } = modalOptions;
    return (
      <Flex align="center">
        <div className={styles.modalTitle}>
          {modalStack?.length && (
            <>
              {modalStack.map((item, index: number) => (
                <span
                  key={item.modalId}
                  style={{ cursor: 'pointer' }}
                  onClick={() => go(item.modalId)}
                >
                  {item.title}
                  {modalStack.length - 1 !== index && (
                    <span style={{ margin: '0 5px' }}>/</span>
                  )}
                </span>
              ))}
            </>
          )}
        </div>

        {headerLeft
          ? typeof headerLeft === 'function'
            ? headerLeft()
            : headerLeft
          : undefined}
      </Flex>
    );
  };

  const close = () => {
    setFalse();
    setTimeout(() => {
      clear();
    }, 300);
  };

  return (
    <HncyModal
      onCancel={close}
      width={modalOptions.w ?? 200}
      height={modalOptions.h ?? 200}
      open={open}
      titleRender={titleRender}
    >
      {open && renderModal()}
    </HncyModal>
  );
};

export default forwardRef(GlobalModalServices);
