import { isValidElement, useImperativeHandle, useRef, useState } from 'react';
import { useMemoizedFn, useReactive } from 'ahooks';
import noop from 'lodash/noop';

import Confirm from './confirm';

// eslint-disable-next-line react/prop-types
function ConfirmHolder({ ref, ...props }) {
  // HACK: 这里默认值不使用 null，来避免开发环境中的字段必填警告
  // HACK: useReactive 无法存储 react-node，所以只能使用 useState
  const [title, setTitle] = useState('');
  const [content, setContent] = useState('');
  const state = useReactive({
    show: false,
    title: '',
    content: '',
    onConfirm: noop,
    onCancel: noop,
    // 其他属性
    loading: false,
    showCancelButton: true,
    showCloseButton: true,
    showConfirmButton: true,
    confirmButtonText: 'Confirm',
    confirmButtonProps: {},
    cancelButtonText: 'Cancel',
    cancelButtonProps: {},
  });
  const open = useMemoizedFn((params = {}) => {
    if (isValidElement(params.title)) {
      setTitle(params.title);
      state.title = '';
    } else {
      setTitle('');
      state.title = params.title;
    }
    if (isValidElement(params.content)) {
      setContent(params.content);
      state.content = '';
    } else {
      setContent('');
      state.content = params.content;
    }
    state.onConfirm = params.onConfirm || noop;
    state.onCancel = params.onCancel || noop;
    state.showCloseButton = params.showCloseButton ?? true;
    state.showCancelButton = params.showCancelButton ?? true;
    state.showConfirmButton = params.showConfirmButton ?? true;
    if (params.confirmButtonText) state.confirmButtonText = params.confirmButtonText;
    if (params.confirmButtonProps) state.confirmButtonProps = params.confirmButtonProps;
    if (params.cancelButtonText) state.cancelButtonText = params.cancelButtonText;
    if (params.cancelButtonProps) state.cancelButtonProps = params.cancelButtonProps;

    state.loading = false;
    state.show = true;
  });
  const reset = useMemoizedFn(() => {
    setTitle('');
    setContent('');
    state.title = '';
    state.content = '';
    state.onConfirm = noop;
    state.onCancel = noop;
    state.confirmButtonText = 'Confirm';
    state.confirmButtonProps = {};
    state.cancelButtonText = 'Cancel';
    state.cancelButtonProps = {};
    state.showConfirmButton = true;
    state.showCancelButton = true;
    state.showCloseButton = true;
  });
  const close = useMemoizedFn(() => {
    state.show = false;
    setTimeout(() => {
      reset();
    }, 300);
  });
  const update = useMemoizedFn((params) => {
    if (params.title) {
      if (isValidElement(params.title)) {
        setTitle(params.title);
        state.title = '';
      } else {
        setTitle('');
        state.title = params.title;
      }
    }
    if (params.content) {
      if (isValidElement(params.content)) {
        setContent(params.content);
        state.content = '';
      } else {
        setContent('');
        state.content = params.content;
      }
    }
  });
  const onCancel = useMemoizedFn((e, reason) => {
    close();
    state?.onCancel(e, reason);
  }, []);
  const onConfirm = useMemoizedFn(async (e) => {
    state.loading = true;
    try {
      await state?.onConfirm(close, e);
    } finally {
      state.loading = false;
    }
  }, []);
  useImperativeHandle(ref, () => {
    return {
      open,
      close,
      update,
    };
  }, [open, close, update]);

  const realTitle = title || state.title;
  const realContent = content || state.content;

  return (
    <Confirm
      {...props}
      open={state.show}
      title={realTitle}
      onConfirm={onConfirm}
      onCancel={onCancel}
      confirmButton={{
        text: state.confirmButtonText,
        props: {
          variant: 'contained',
          color: 'primary',
          loading: state.loading,
          ...state.confirmButtonProps,
        },
      }}
      showCloseButton={state.showCloseButton}
      showCancelButton={state.showCancelButton}
      showConfirmButton={state.showConfirmButton}
      cancelButton={{
        text: state.cancelButtonText,
        props: {
          variant: 'outlined',
          color: 'primary',
          ...state.cancelButtonProps,
        },
      }}>
      {realContent instanceof Function ? realContent() : realContent}
    </Confirm>
  );
}

export default function useConfirm(props = {}) {
  const confirmRef = useRef(null);

  /**
   * 打开一个弹窗
   * @type {import('./types').OpenConfirm}
   */
  const open = useMemoizedFn((...args) => {
    confirmRef.current?.open(...args);
  });
  /**
   * 关闭一个弹窗
   * @type {import('./types').CloseConfirm}
   */
  const close = useMemoizedFn((...args) => {
    confirmRef.current?.close(...args);
  });

  /**
   * 更新弹窗的 title 和 content
   * @type {import('./types').UpdateConfirm}
   */
  const update = useMemoizedFn((...args) => {
    confirmRef.current?.update(...args);
  });
  const confirmApi = {
    open,
    close,
    update,
  };

  return {
    confirmHolder: <ConfirmHolder {...props} ref={confirmRef} />,
    confirmApi,
  };
}
