import React, { useEffect, useState, useRef } from "react";
import ReactDOM from "react-dom";
import { Modal, ModalProps } from "./ModalMain";
import { Button, ButtonProps } from "../button";
import { ModalMessage, ModalMessageProps } from "./ModalMessage";
import { useTranslation } from "../i18n";
import { ConfigProvider } from "../configprovider";
import { noop } from "../_util/noop";

/**
 * `Modal.confirm` 方法接收以下参数：
 */
export interface ConfirmOptions
  extends Pick<
    ModalProps,
    | "size"
    | "popupContainer"
    | "caption"
    | "maskStyle"
    | "maskClosable"
    | "className"
    | "style"
  > {
  /**
   * 要询问的消息
   */
  message: React.ReactNode;

  /**
   * 可选的详细解释
   */
  description?: React.ReactNode;

  /**
   * 确认按钮的文案
   */
  okText?: React.ReactNode;

  /**
   * 确认按钮类型
   *
   * @default primary
   *
   * @since 2.7.4
   */
  okType?: ButtonProps["type"];

  /**
   * 取消按钮的文案
   */
  cancelText?: React.ReactNode;

  /**
   * 取消按钮类型
   *
   * @default weak
   *
   * @since 2.7.4
   */
  cancelType?: ButtonProps["type"];

  /**
   * 提示图标
   * @since 2.4.2
   */
  icon?: ModalMessageProps["icon"];

  /**
   * 是否禁用关闭图标
   *
   * **默认情况下会显示，关闭对话框认为是取消操作**
   * @default false
   */
  disableCloseIcon?: boolean;

  /**
   * 点击确定按钮回调
   *
   * `Promise` 可触发按钮 loading
   * @since 2.5.0
   */
  onOk?: () => void | Promise<void>;

  /**
   * 点击取消按钮回调
   *
   * `Promise` 可触发按钮 loading
   * @since 2.5.0
   */
  onCancel?: () => void | Promise<void>;
}

/**
 * API 的方式唤起一个确认对话框
 * @param options
 * @returns 异步返回布尔值，为 true 则表示用户确认，为 false 则表示用户取消
 */
export function confirm(options: ConfirmOptions) {
  const { onOk = noop, onCancel = noop, ...restOptions } = options;
  return new Promise<boolean>(resolve => {
    const el = document.createElement("div");
    ReactDOM.render(
      <ConfigProvider>
        <ModalConfirmAPI
          {...restOptions}
          onOk={async () => {
            await onOk();
            resolve(true);
          }}
          onCancel={async () => {
            await onCancel();
            resolve(false);
          }}
          onExited={() => {
            ReactDOM.unmountComponentAtNode(el);
          }}
        />
      </ConfigProvider>,
      el
    );
  });
}

function ModalConfirmAPI({
  onOk,
  onCancel,
  ...confirmModalProps
}: ModalConfirmProps) {
  const [visible, setVisible] = useState(false);

  // 渲染之后，马上显示
  useEffect(() => setVisible(true), []);

  const ok = async () => {
    await onOk();
    setVisible(false);
  };

  const cancel = async () => {
    await onCancel();
    setVisible(false);
  };

  return (
    <ModalConfirm
      visible={visible}
      onOk={ok}
      onCancel={cancel}
      onClose={cancel}
      {...confirmModalProps}
    />
  );
}

export interface ModalConfirmProps extends ConfirmOptions, ModalProps {}

/**
 * 提供原始的 ModalConfirm 组件。
 * 推荐使用 `Modal.confirm()` API 来简化用法
 */
export function ModalConfirm({
  message,
  description,
  icon,
  ...modalProps
}: ModalConfirmProps) {
  useEffect(() => {
    window.focus();
  }, []);
  return (
    <Modal disableEscape {...modalProps}>
      <Modal.Body>
        <ModalMessage icon={icon} message={message} description={description} />
      </Modal.Body>
      <Modal.Footer>
        <ModalButton {...modalProps} />
      </Modal.Footer>
    </Modal>
  );
}

function ModalButton({
  onOk,
  okText,
  okType = "primary",
  onCancel,
  cancelText,
  cancelType = "weak",
}: Partial<ModalConfirmProps>) {
  const t = useTranslation();
  const mainButtonRef = useRef<HTMLButtonElement>(null);
  const [okLoading, setOkLoading] = useState(false);
  const [cancelLoading, setCancelLoading] = useState(false);

  useEffect(() => {
    if (mainButtonRef.current) {
      mainButtonRef.current.focus();
    }
  }, []);
  return (
    <>
      <Button
        type={okType}
        htmlType="button"
        loading={okLoading}
        disabled={cancelLoading}
        onClick={async () => {
          setOkLoading(true);
          await onOk();
          setOkLoading(false);
        }}
        ref={mainButtonRef}
      >
        {okText || t.okText}
      </Button>
      <Button
        type={cancelType}
        htmlType="button"
        loading={cancelLoading}
        disabled={okLoading}
        onClick={async () => {
          setCancelLoading(true);
          await onCancel();
          setCancelLoading(false);
        }}
      >
        {cancelText || t.cancelText}
      </Button>
    </>
  );
}
