/* eslint-disable import/no-mutable-exports */
import { ERROR_KEYS } from '@/@types/errors';
import { Media } from '@/styles/media';
import { getDevice } from '@/utils/device';
import type { MessageInstance } from 'antd/es/message/interface';
import type { NotificationInstance } from 'antd/es/notification/interface';
import type { ReactNode } from 'react';
import { message as antdMessage, notification as antdNotification } from 'ui/elements';

export let message: Readonly<MessageInstance>;
export let notification: Readonly<NotificationInstance>;

function createWrapper<T extends NotificationInstance, M extends MessageInstance>(
  notificationObj: T,
  messageObj: M
): T {
  const handler: ProxyHandler<T> = {
    get(target, prop, receiver) {
      const notificationMethod = target[prop as keyof T];
      const messageMethod = messageObj[prop as keyof M];

      if (typeof notificationMethod === 'function' && typeof messageMethod === 'function') {
        return function (...args: any[]) {
          const device = getDevice();

          if (device?.isMobile) {
            if (typeof args[0] === 'object') {
              if (ERROR_KEYS.includes(args[0].key)) return;
              args[0].content = args[0].description || args[0].message;
            }

            messageMethod.apply(messageObj, args);
          }

          notificationMethod.apply(target, args);
        };
      }

      return Reflect.get(target, prop, receiver);
    },
  };

  return new Proxy(notificationObj, handler);
}

export function Notification({ children }: { readonly children?: ReactNode }) {
  const device = getDevice();

  const [messageApi, messageContextHolder] = antdMessage.useMessage({
    duration: device?.isMobile ? 1.5 : 1.2,
    maxCount: 3,
    top: 70,
  });

  const [notificationApi, notificationContextHolder] = antdNotification.useNotification({
    maxCount: 3,
    placement: 'bottomRight',
    stack: { threshold: 1 },
  });

  message = messageApi;
  notification = createWrapper(notificationApi, messageApi);

  return (
    <>
      {messageContextHolder}
      <Media greaterThanOrEqual="laptop">{notificationContextHolder}</Media>
      {children}
    </>
  );
}
