import { unmountComponentAtNode, render as DOMRender } from 'react-dom';

import { ConfirmDialog } from './confirm-dialog';
import { destroyFns } from './destroyFns';
import type { ConfigUpdate, DialogFuncProps } from './types';

export function confirm(config: DialogFuncProps) {
  const container = document.createDocumentFragment();
  let currentConfig = { ...config, close, open: true };
  let timeoutId: NodeJS.Timeout;

  function close() {
    currentConfig = {
      ...currentConfig,
      open: false,
    };

    render(currentConfig);
    config.afterClose?.();
    destroy();
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  function destroy(...args: any[]) {
    const triggerCancel = args.some(param => param && param.triggerCancel);

    if (config.onCancel && triggerCancel) {
      config.onCancel(() => {}, ...args.slice(1));
    }

    for (let i = 0; i < destroyFns.length; i++) {
      const fn = destroyFns[i];

      if (fn === close) {
        destroyFns.splice(i, 1);
        break;
      }
    }

    unmountComponentAtNode(container);
  }

  function render({ okText, cancelText, ...delegated }: any) {
    clearTimeout(timeoutId);

    timeoutId = setTimeout(() => {
      DOMRender(<ConfirmDialog {...delegated} okText={okText} cancelText={cancelText} />, container);
    });
  }

  function update(configUpdate: ConfigUpdate) {
    if (typeof configUpdate === 'function') {
      currentConfig = configUpdate(currentConfig);
    } else {
      currentConfig = {
        ...currentConfig,
        ...configUpdate,
      };
    }

    render(currentConfig);
  }

  render(currentConfig);

  destroyFns.push(close);

  return {
    destroy: close,
    update,
  };
}

const dumbFn = (event: Event) => {
  event.preventDefault();
};

export function withDialog(delegated: DialogFuncProps): DialogFuncProps {
  return {
    open: true,
    displayCancel: true,
    displayOk: true,
    ...delegated,
  };
}

export function withWarning(delegated: DialogFuncProps): DialogFuncProps {
  return {
    open: true,
    displayCancel: false,
    displayOk: true,
    type: 'warning',
    ...delegated,
    onInteractOutside: dumbFn,
    onPointerDownOutside: dumbFn,
  };
}

export function withError(delegated: DialogFuncProps): DialogFuncProps {
  return {
    open: true,
    displayOk: true,
    displayCancel: false,
    type: 'error',
    ...delegated,
    onInteractOutside: dumbFn,
    onPointerDownOutside: dumbFn,
  };
}

export function withInfo(delegated: DialogFuncProps): DialogFuncProps {
  return {
    open: true,
    displayOk: true,
    displayCancel: false,
    type: 'info',
    ...delegated,
    onInteractOutside: dumbFn,
    onPointerDownOutside: dumbFn,
  };
}

export function withConfirm(delegated: DialogFuncProps): DialogFuncProps {
  return {
    open: true,
    displayOk: true,
    displayCancel: true,
    type: 'info',
    ...delegated,
    onInteractOutside: dumbFn,
    onPointerDownOutside: dumbFn,
  };
}
