import PropTypes from 'prop-types';
import { useCallback, useEffect, useMemo } from 'react';
import { IconButton, Badge } from '@mui/material';
import { useSnackbar } from 'notistack';
import NotificationsOutlinedIcon from '@arcblock/icons/lib/Notification';
import { useCreation } from 'ahooks';
import { EVENTS, WELLKNOWN_SERVICE_PATH_PREFIX, ROLES } from '@abtnode/constant';
import useBrowser from '@arcblock/react-hooks/lib/useBrowser';
import { compareVersions } from '@arcblock/ux/lib/Util';
import { joinURL, withQuery } from 'ufo';
import { useListenWsClient } from './ws';
import NotificationSnackbar from '../Notifications/Snackbar';

const viewAllUrl = joinURL(WELLKNOWN_SERVICE_PATH_PREFIX, 'user', 'notifications');

const getNotificationLink = (notification) => {
  return withQuery(viewAllUrl, {
    id: notification.id,
    severity: notification.severity || 'all',
    componentDid: notification.source === 'system' ? 'system' : notification.componentDid || 'all',
  });
};

export default function NotificationAddon({ session = {} }) {
  const { unReadCount, user, setUnReadCount } = session;
  const userDid = useCreation(() => user?.did, [user]);

  const isAdmin = useCreation(() => user?.role && [ROLES.ADMIN, ROLES.OWNER].includes(user?.role), [user?.role]);

  const { enqueueSnackbar } = useSnackbar();
  const browser = useBrowser();

  const isPreviewUser = useMemo(() => {
    return !userDid || user?.isPreviewUser || userDid === window.blocklet.did;
  }, [userDid, user]);

  // 在 ArcSphere 和 Wallet 端隐藏， 消息的 toast 提示，因为有 native 的通知
  const hiddenNotificationToast = useMemo(() => {
    return browser.arcSphere || browser.wallet;
  }, [browser]);

  const serverVersion = useCreation(() => {
    return window.blocklet?.serverVersion;
  }, []);

  const wsClient = useListenWsClient('user');

  const listenEvent = useCreation(
    () => `${window.blocklet.did}/${userDid}/${EVENTS.NOTIFICATION_BLOCKLET_CREATE}`,
    [userDid]
  );
  const readListenEvent = useCreation(
    () => `${window.blocklet.did}/${userDid}/${EVENTS.NOTIFICATION_BLOCKLET_READ}`,
    [userDid]
  );

  const listenCallback = useCallback(
    (notification) => {
      const { receivers, source } = notification ?? {};

      const { receiver: notificationReceiver } = receivers[0] ?? {};
      const shouldUpdate = isAdmin || source !== 'system';
      if (notificationReceiver === userDid && shouldUpdate) {
        setUnReadCount((x) => x + 1);
        // 显示通知, 如果是系统通知则不需要显示, 如果是移动端不需要显示
        // 兼容代码，如果 server 没有升级那么不需要提示
        const isCompatible = compareVersions(serverVersion, '1.16.42-beta-20250407');
        if (!hiddenNotificationToast && notification.source === 'component' && isCompatible) {
          const link = getNotificationLink(notification);
          const { severity, description } = notification || {};
          const disableAutoHide = ['error', 'warning'].includes(severity) || notification.sticky;
          enqueueSnackbar(description, {
            variant: severity,
            autoHideDuration: disableAutoHide ? null : 5000,
            anchorOrigin: {
              vertical: 'top',
              horizontal: 'center',
            },
            // eslint-disable-next-line react/no-unstable-nested-components
            content: (key) => <NotificationSnackbar viewAllUrl={link} keyId={key} notification={notification} />,
          });
        }
      }
    },
    [userDid, setUnReadCount, enqueueSnackbar, serverVersion, hiddenNotificationToast, isAdmin]
  );

  const readListenCallback = useCallback(
    (data) => {
      const { receiver, readCount } = data ?? {};

      if (receiver === userDid) {
        setUnReadCount((x) => Math.max(x - readCount, 0));
      }
    },
    [userDid, setUnReadCount]
  );

  useEffect(() => {
    if (wsClient && !isPreviewUser) {
      wsClient.on(listenEvent, listenCallback);
      wsClient.on(readListenEvent, readListenCallback);
    }
    return () => {
      if (wsClient && !isPreviewUser) {
        wsClient.off(listenEvent, listenCallback);
        wsClient.off(readListenEvent, readListenCallback);
      }
    };
  }, [wsClient, setUnReadCount, listenCallback, listenEvent, readListenCallback, readListenEvent, isPreviewUser]);

  if (!session.user || !viewAllUrl) {
    return null;
  }

  return (
    <IconButton
      size="medium"
      variant="outlined"
      href={withQuery(viewAllUrl, { read: unReadCount <= 0 })}
      sx={{
        '&:hover': {
          borderRadius: '50%',
        },
      }}>
      <Badge badgeContent={unReadCount} color="error" invisible={unReadCount === 0}>
        <NotificationsOutlinedIcon style={{ width: 'auto', height: 24 }} />
      </Badge>
    </IconButton>
  );
}

NotificationAddon.propTypes = {
  session: PropTypes.object,
};
