import React, { MouseEventHandler, forwardRef, useCallback, useRef, useState } from 'react';
import { Room } from 'matrix-js-sdk';
import {
  Avatar,
  Box,
  Button,
  Dialog,
  Header,
  Icon,
  IconButton,
  Icons,
  Input,
  Text,
  Menu,
  MenuItem,
  Overlay,
  OverlayBackdrop,
  OverlayCenter,
  config,
  PopOut,
  toRem,
  Line,
  RectCords,
  Badge,
  Spinner,
} from 'folds';
import { useFocusWithin, useHover } from 'react-aria';
import FocusTrap from 'focus-trap-react';
import { useAtom, useAtomValue } from 'jotai';
import dayjs from 'dayjs';
import isToday from 'dayjs/plugin/isToday';
import isYesterday from 'dayjs/plugin/isYesterday';
import { NavItem, NavItemContent, NavItemOptions, NavLink } from '../../components/nav';
import { UnreadBadge, UnreadBadgeCenter } from '../../components/unread-badge';
import { RoomAvatar, RoomIcon } from '../../components/room-avatar';
import { getDirectRoomAvatarUrl, getRoomAvatarUrl, getStateEvent } from '../../utils/room';
import { nameInitials } from '../../utils/common';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { useRoomUnread } from '../../state/hooks/unread';
import { roomToUnreadAtom } from '../../state/room/roomToUnread';
import { getPowersLevelFromMatrixEvent, usePowerLevels } from '../../hooks/usePowerLevels';
import { markAsRead } from '../../utils/notifications';
import { UseStateProvider } from '../../components/UseStateProvider';
import { LeaveRoomPrompt } from '../../components/leave-room-prompt';
import { useRoomTypingMember } from '../../hooks/useRoomTypingMembers';
import { TypingIndicator } from '../../components/typing-indicator';
import { stopPropagation } from '../../utils/keyboard';
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
import { useSetting } from '../../state/hooks/settings';
import { settingsAtom } from '../../state/settings';
import { useOpenRoomSettings } from '../../state/hooks/roomSettings';
import { useSpaceOptionally } from '../../hooks/useSpace';
import {
  getRoomNotificationModeIcon,
  RoomNotificationMode,
} from '../../hooks/useRoomsNotificationPreferences';
import { RoomNotificationModeSwitcher } from '../../components/RoomNotificationSwitcher';
import { getRoomCreatorsForRoomId, useRoomCreators } from '../../hooks/useRoomCreators';
import { getRoomPermissionsAPI, useRoomPermissions } from '../../hooks/useRoomPermissions';
import { InviteUserPrompt } from '../../components/invite-user-prompt';
import {
  LOCAL_ROOM_NAMES_KEY,
  getLocalRoomNamesContent,
  useHasLocalRoomName,
  useLocalRoomName,
} from '../../hooks/useRoomMeta';
import { useCallMembers, useCallSession } from '../../hooks/useCall';
import { useCallEmbed, useCallStart } from '../../hooks/useCallEmbed';
import { callChatAtom } from '../../state/callEmbed';
import { useCallPreferencesAtom } from '../../state/hooks/callPreferences';
import { useAutoDiscoveryInfo } from '../../hooks/useAutoDiscoveryInfo';
import { livekitSupport } from '../../hooks/useLivekitSupport';
import { MessageEvent, StateEvent } from '../../../types/matrix/room';
import { webRTCSupported } from '../../utils/rtc';
import { useRoomLatestRenderedEvent } from '../../hooks/useRoomLatestRenderedEvent';

dayjs.extend(isToday);
dayjs.extend(isYesterday);

const PREVIEW_MAX_CHARS = 48;

function formatDmTimestamp(ts: number): string {
  const d = dayjs(ts);
  const now = dayjs();
  const diffMinutes = now.diff(d, 'minute');
  if (diffMinutes < 60) {
    return `${diffMinutes < 1 ? 0 : diffMinutes}m`;
  }
  const diffHours = now.diff(d, 'hour');
  if (diffHours < 24) {
    return `${diffHours}h`;
  }
  if (d.isYesterday()) {
    return 'Yesterday';
  }
  return d.format('D MMM');
}

type RenameRoomDialogProps = {
  room: Room;
  onClose: () => void;
};
function RenameRoomDialog({ room, onClose }: RenameRoomDialogProps) {
  const mx = useMatrixClient();
  const inputRef = useRef<HTMLInputElement>(null);

  const getCurrentLocalName = useCallback((): string => {
    const content = getLocalRoomNamesContent(mx);
    return content.rooms[room.roomId] ?? '';
  }, [mx, room.roomId]);

  const handleSave = useCallback(() => {
    const newName = inputRef.current?.value.trim() ?? '';
    if (newName.length > 255) return;
    const existing = getLocalRoomNamesContent(mx);
    if (newName === '') {
      const { [room.roomId]: _removed, ...rest } = existing.rooms;
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (mx as any).setAccountData(LOCAL_ROOM_NAMES_KEY, { rooms: rest });
    } else {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (mx as any).setAccountData(LOCAL_ROOM_NAMES_KEY, {
        rooms: { ...existing.rooms, [room.roomId]: newName },
      });
    }
    onClose();
  }, [mx, room.roomId, onClose]);

  const handleClear = useCallback(() => {
    const existing = getLocalRoomNamesContent(mx);
    const { [room.roomId]: _removed, ...rest } = existing.rooms;
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    (mx as any).setAccountData(LOCAL_ROOM_NAMES_KEY, { rooms: rest });
    onClose();
  }, [mx, room.roomId, onClose]);

  const handleKeyDown = (evt: React.KeyboardEvent<HTMLInputElement>) => {
    if (evt.key === 'Enter') handleSave();
    if (evt.key === 'Escape') onClose();
  };

  return (
    <Overlay open backdrop={<OverlayBackdrop />}>
      <OverlayCenter>
        <FocusTrap
          focusTrapOptions={{
            initialFocus: false,
            onDeactivate: onClose,
            clickOutsideDeactivates: true,
            escapeDeactivates: stopPropagation,
          }}
        >
          <Dialog variant="Surface" aria-labelledby="rename-room-dialog-title">
            <Header
              style={{
                padding: `0 ${config.space.S200} 0 ${config.space.S400}`,
                borderBottomWidth: config.borderWidth.B300,
              }}
              variant="Surface"
              size="500"
            >
              <Box grow="Yes">
                <Text as="h2" size="H4" id="rename-room-dialog-title">
                  Rename room (for you only)
                </Text>
              </Box>
              <IconButton size="300" onClick={onClose} radii="300" aria-label="Cancel">
                <Icon src={Icons.Cross} />
              </IconButton>
            </Header>
            <Box style={{ padding: config.space.S400 }} direction="Column" gap="400">
              <Box direction="Column" gap="200">
                <Text size="L400">Custom name</Text>
                <Input
                  ref={inputRef}
                  defaultValue={getCurrentLocalName()}
                  placeholder={room.name}
                  variant="Secondary"
                  radii="300"
                  maxLength={255}
                  onKeyDown={handleKeyDown}
                  autoFocus
                />
                <Text size="T300" priority="300">
                  Only visible to you. Leave blank to use the original name.
                </Text>
              </Box>
              <Box gap="300">
                <Box grow="Yes">
                  <Button
                    onClick={handleClear}
                    variant="Secondary"
                    fill="Soft"
                    radii="300"
                    style={{ width: '100%' }}
                  >
                    <Text size="B400">Clear</Text>
                  </Button>
                </Box>
                <Box grow="Yes">
                  <Button
                    onClick={handleSave}
                    variant="Primary"
                    radii="300"
                    style={{ width: '100%' }}
                  >
                    <Text size="B400">Save</Text>
                  </Button>
                </Box>
              </Box>
            </Box>
          </Dialog>
        </FocusTrap>
      </OverlayCenter>
    </Overlay>
  );
}

// localStorage key for timed mute timers
const MUTE_TIMERS_KEY = 'io.lotus.mute_timers';

type MuteTimerEntry = { roomId: string; unmuteAt: number };

function loadMuteTimers(): MuteTimerEntry[] {
  try {
    return JSON.parse(localStorage.getItem(MUTE_TIMERS_KEY) ?? '[]');
  } catch {
    return [];
  }
}

function saveMuteTimers(timers: MuteTimerEntry[]): void {
  localStorage.setItem(MUTE_TIMERS_KEY, JSON.stringify(timers));
}

function scheduleMuteTimer(roomId: string, durationMs: number, onUnmute: () => void): void {
  const unmuteAt = Date.now() + durationMs;
  const existing = loadMuteTimers().filter((e) => e.roomId !== roomId);
  saveMuteTimers([...existing, { roomId, unmuteAt }]);
  setTimeout(onUnmute, durationMs);
}

type RoomNavItemMenuProps = {
  room: Room;
  requestClose: () => void;
  onRenameClick: () => void;
  notificationMode?: RoomNotificationMode;
};
const RoomNavItemMenu = forwardRef<HTMLDivElement, RoomNavItemMenuProps>(
  ({ room, requestClose, onRenameClick, notificationMode }, ref) => {
    const mx = useMatrixClient();
    const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
    const unread = useRoomUnread(room.roomId, roomToUnreadAtom);
    const powerLevels = usePowerLevels(room);
    const creators = useRoomCreators(room);

    const permissions = useRoomPermissions(creators, powerLevels);
    const canInvite = permissions.action('invite', mx.getSafeUserId());
    const openRoomSettings = useOpenRoomSettings();
    const space = useSpaceOptionally();

    const [invitePrompt, setInvitePrompt] = useState(false);
    const [copiedLink, setCopiedLink] = useState(false);
    const isServerNotice = room.getType() === 'm.server_notice';

    const isFavorite = !!room.tags?.['m.favourite'];

    const handleToggleFavorite = () => {
      if (isFavorite) {
        mx.deleteRoomTag(room.roomId, 'm.favourite');
      } else {
        mx.setRoomTag(room.roomId, 'm.favourite', { order: 0.5 });
      }
      requestClose();
    };

    const handleMarkAsRead = () => {
      markAsRead(mx, room.roomId, hideActivity);
      requestClose();
    };

    const handleCopyRoomLink = () => {
      const roomAlias = room.getCanonicalAlias() ?? room.roomId;
      const link = `https://matrix.to/#/${encodeURIComponent(roomAlias)}`;
      navigator.clipboard.writeText(link).catch(() => {});
      setCopiedLink(true);
      setTimeout(() => setCopiedLink(false), 1500);
    };

    const handleMuteFor = useCallback(
      async (durationMs: number | null) => {
        const { setRoomNotificationPreference } =
          await import('../../hooks/useRoomsNotificationPreferences');
        const prevMode = notificationMode ?? RoomNotificationMode.Unset;
        await setRoomNotificationPreference(
          mx,
          room.roomId,
          RoomNotificationMode.Mute,
          prevMode,
        ).catch(() => {});
        if (durationMs !== null) {
          scheduleMuteTimer(room.roomId, durationMs, () => {
            setRoomNotificationPreference(
              mx,
              room.roomId,
              RoomNotificationMode.Unset,
              RoomNotificationMode.Mute,
            ).catch(() => {});
            saveMuteTimers(loadMuteTimers().filter((e) => e.roomId !== room.roomId));
          });
        }
        requestClose();
      },
      [mx, room.roomId, notificationMode, requestClose],
    );

    const handleInvite = () => {
      setInvitePrompt(true);
    };

    const handleRoomSettings = () => {
      openRoomSettings(room.roomId, space?.roomId);
      requestClose();
    };

    const isMuted = notificationMode === RoomNotificationMode.Mute;

    return (
      <Menu ref={ref} style={{ maxWidth: toRem(180), width: '100vw' }}>
        {invitePrompt && room && (
          <InviteUserPrompt
            room={room}
            requestClose={() => {
              setInvitePrompt(false);
              requestClose();
            }}
          />
        )}
        <Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
          <MenuItem
            onClick={handleMarkAsRead}
            size="300"
            after={<Icon size="100" src={Icons.CheckTwice} />}
            radii="300"
            disabled={!unread}
          >
            <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
              Mark as Read
            </Text>
          </MenuItem>
          <MenuItem
            onClick={handleCopyRoomLink}
            size="300"
            after={<Icon size="100" src={Icons.Link} />}
            radii="300"
          >
            <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
              {copiedLink ? 'Copied!' : 'Copy Link'}
            </Text>
          </MenuItem>
          <RoomNotificationModeSwitcher roomId={room.roomId} value={notificationMode}>
            {(handleOpen, opened, changing) => (
              <MenuItem
                size="300"
                after={
                  changing ? (
                    <Spinner size="100" variant="Secondary" />
                  ) : (
                    <Icon size="100" src={getRoomNotificationModeIcon(notificationMode)} />
                  )
                }
                radii="300"
                aria-pressed={opened}
                onClick={handleOpen}
              >
                <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                  Notifications
                </Text>
              </MenuItem>
            )}
          </RoomNotificationModeSwitcher>
        </Box>
        {!isMuted && (
          <>
            <Line variant="Surface" size="300" />
            <Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
              <MenuItem
                size="300"
                after={<Icon size="100" src={Icons.BellMute} />}
                radii="300"
                onClick={() => handleMuteFor(15 * 60 * 1000)}
              >
                <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                  Mute for 15m
                </Text>
              </MenuItem>
              <MenuItem
                size="300"
                after={<Icon size="100" src={Icons.BellMute} />}
                radii="300"
                onClick={() => handleMuteFor(60 * 60 * 1000)}
              >
                <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                  Mute for 1h
                </Text>
              </MenuItem>
              <MenuItem
                size="300"
                after={<Icon size="100" src={Icons.BellMute} />}
                radii="300"
                onClick={() => handleMuteFor(8 * 60 * 60 * 1000)}
              >
                <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                  Mute for 8h
                </Text>
              </MenuItem>
              <MenuItem
                size="300"
                after={<Icon size="100" src={Icons.BellMute} />}
                radii="300"
                onClick={() => handleMuteFor(24 * 60 * 60 * 1000)}
              >
                <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                  Mute for 24h
                </Text>
              </MenuItem>
              <MenuItem
                size="300"
                after={<Icon size="100" src={Icons.BellMute} />}
                radii="300"
                onClick={() => handleMuteFor(null)}
              >
                <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                  Mute indefinitely
                </Text>
              </MenuItem>
            </Box>
          </>
        )}
        <Line variant="Surface" size="300" />
        <Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
          <MenuItem
            onClick={handleToggleFavorite}
            size="300"
            after={<Icon size="100" src={Icons.Star} filled={isFavorite} />}
            radii="300"
            aria-pressed={isFavorite}
          >
            <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
              {isFavorite ? 'Remove from Favorites' : 'Add to Favorites'}
            </Text>
          </MenuItem>
          <MenuItem
            onClick={handleInvite}
            variant="Primary"
            fill="None"
            size="300"
            after={<Icon size="100" src={Icons.UserPlus} />}
            radii="300"
            aria-pressed={invitePrompt}
            disabled={!canInvite}
          >
            <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
              Invite
            </Text>
          </MenuItem>
          <MenuItem
            onClick={() => {
              requestClose();
              onRenameClick();
            }}
            size="300"
            after={<Icon size="100" src={Icons.Pencil} />}
            radii="300"
          >
            <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
              Rename for me…
            </Text>
          </MenuItem>
          {!isServerNotice && (
            <MenuItem
              onClick={handleRoomSettings}
              size="300"
              after={<Icon size="100" src={Icons.Setting} />}
              radii="300"
            >
              <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                Room Settings
              </Text>
            </MenuItem>
          )}
        </Box>
        <Line variant="Surface" size="300" />
        <Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
          <UseStateProvider initial={false}>
            {(promptLeave, setPromptLeave) => (
              <>
                <MenuItem
                  onClick={() => setPromptLeave(true)}
                  variant="Critical"
                  fill="None"
                  size="300"
                  after={<Icon size="100" src={Icons.ArrowGoLeft} />}
                  radii="300"
                  aria-pressed={promptLeave}
                >
                  <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                    Leave Room
                  </Text>
                </MenuItem>
                {promptLeave && (
                  <LeaveRoomPrompt
                    roomId={room.roomId}
                    onDone={requestClose}
                    onCancel={() => setPromptLeave(false)}
                  />
                )}
              </>
            )}
          </UseStateProvider>
        </Box>
      </Menu>
    );
  },
);

function CallChatToggle() {
  const [chat, setChat] = useAtom(callChatAtom);

  return (
    <IconButton
      onClick={() => setChat(!chat)}
      aria-pressed={chat}
      aria-label="Toggle Chat"
      variant="Background"
      fill="None"
      size="300"
      radii="300"
    >
      <Icon size="50" src={Icons.Message} filled={chat} />
    </IconButton>
  );
}

type RoomNavItemProps = {
  room: Room;
  selected: boolean;
  linkPath: string;
  notificationMode?: RoomNotificationMode;
  showAvatar?: boolean;
  direct?: boolean;
};
function RoomNavItem_({
  room,
  selected,
  showAvatar,
  direct,
  notificationMode,
  linkPath,
}: RoomNavItemProps) {
  const isFavorite = !!room.tags?.['m.favourite'];
  const mx = useMatrixClient();
  const useAuthentication = useMediaAuthentication();
  const [hover, setHover] = useState(false);
  const { hoverProps } = useHover({ onHoverChange: setHover });
  const { focusWithinProps } = useFocusWithin({ onFocusWithinChange: setHover });
  const [menuAnchor, setMenuAnchor] = useState<RectCords>();
  const [renameDialog, setRenameDialog] = useState(false);
  const unread = useRoomUnread(room.roomId, roomToUnreadAtom);
  const typingMember = useRoomTypingMember(room.roomId).filter(
    (receipt) => receipt.userId !== mx.getUserId(),
  );

  const roomName = useLocalRoomName(room);
  const hasLocalName = useHasLocalRoomName(room.roomId);

  const latestEvent = useRoomLatestRenderedEvent(room);
  const dmPreview = (() => {
    if (!direct || !latestEvent) return null;
    const type = latestEvent.getType();
    const ts = latestEvent.getTs();
    if (!ts) return null;
    // Skip pure membership events
    if (type === StateEvent.RoomMember) return null;
    let body: string;
    if (latestEvent.isDecryptionFailure()) {
      body = 'Encrypted message';
    } else if (type === MessageEvent.Sticker) {
      body = 'Sticker';
    } else {
      const rawBody: unknown = latestEvent.getContent()?.body;
      body = typeof rawBody === 'string' ? rawBody.replace(/\s+/g, ' ').trim() : '';
    }
    if (!body) return null;
    const preview = body.length > PREVIEW_MAX_CHARS ? `${body.slice(0, PREVIEW_MAX_CHARS)}…` : body;
    return { preview, time: formatDmTimestamp(ts) };
  })();

  const handleContextMenu: MouseEventHandler<HTMLElement> = (evt) => {
    evt.preventDefault();
    setMenuAnchor({
      x: evt.clientX,
      y: evt.clientY,
      width: 0,
      height: 0,
    });
  };

  const handleOpenMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
    setMenuAnchor(evt.currentTarget.getBoundingClientRect());
  };

  const optionsVisible = hover || !!menuAnchor;
  const callSession = useCallSession(room);
  const callMembers = useCallMembers(callSession);
  const startCall = useCallStart(direct);
  const callEmbed = useCallEmbed();
  const callPref = useAtomValue(useCallPreferencesAtom());
  const autoDiscoveryInfo = useAutoDiscoveryInfo();

  const handleStartCall: MouseEventHandler<HTMLAnchorElement> = (evt) => {
    const powerLevelsEvent = getStateEvent(room, StateEvent.RoomPowerLevels);
    const powerLevels = getPowersLevelFromMatrixEvent(powerLevelsEvent);
    const creators = getRoomCreatorsForRoomId(mx, room.roomId);
    const permissions = getRoomPermissionsAPI(creators, powerLevels);

    const hasCallPermission = permissions.stateEvent(
      StateEvent.GroupCallMemberPrefix,
      mx.getSafeUserId(),
    );

    // Do not join if missing permissions or no livekit support or no webRTC support
    if (!hasCallPermission || !livekitSupport(autoDiscoveryInfo) || !webRTCSupported()) {
      return;
    }

    // Do not join if already in call
    if (callEmbed) {
      return;
    }
    // Start call in second click
    if (selected) {
      evt.preventDefault();
      startCall(room, callPref);
    }
  };

  return (
    <NavItem
      variant="Background"
      radii="400"
      highlight={unread !== undefined}
      aria-selected={selected}
      data-hover={!!menuAnchor}
      onContextMenu={handleContextMenu}
      {...hoverProps}
      {...focusWithinProps}
    >
      <NavLink to={linkPath} onClick={room.isCallRoom() ? handleStartCall : undefined}>
        <NavItemContent>
          <Box as="span" grow="Yes" alignItems="Center" gap="200">
            <Avatar size="200" radii="400">
              {showAvatar ? (
                <RoomAvatar
                  roomId={room.roomId}
                  src={
                    direct
                      ? getDirectRoomAvatarUrl(mx, room, 96, useAuthentication)
                      : getRoomAvatarUrl(mx, room, 96, useAuthentication)
                  }
                  alt={roomName}
                  renderFallback={() => (
                    <Text as="span" size="H6">
                      {nameInitials(roomName)}
                    </Text>
                  )}
                />
              ) : (
                <RoomIcon
                  style={{
                    opacity: unread ? config.opacity.P500 : config.opacity.P300,
                  }}
                  filled={selected}
                  size="100"
                  joinRule={room.getJoinRule()}
                  roomType={room.getType()}
                />
              )}
            </Avatar>
            <Box as="span" direction="Column" grow="Yes" style={{ minWidth: 0 }}>
              <Box as="span" grow="Yes" alignItems="Center" gap="100">
                <Text priority={unread ? '500' : '300'} as="span" size="Inherit" truncate>
                  {roomName}
                </Text>
                {hasLocalName && (
                  <Icon
                    size="50"
                    src={Icons.Pencil}
                    aria-label="Custom local name"
                    style={{ opacity: config.opacity.P300, flexShrink: 0 }}
                  />
                )}
                {isFavorite && (
                  <Icon
                    size="50"
                    src={Icons.Star}
                    filled
                    aria-label="Favorited"
                    style={{ opacity: config.opacity.P300, flexShrink: 0 }}
                  />
                )}
              </Box>
              {dmPreview && (
                <Box as="span" alignItems="Center" gap="100" style={{ minWidth: 0 }}>
                  <Text
                    as="span"
                    size="T200"
                    truncate
                    style={{ opacity: config.opacity.P300, flexGrow: 1 }}
                  >
                    {dmPreview.preview}
                  </Text>
                  <Text
                    as="span"
                    size="T200"
                    style={{ opacity: config.opacity.P300, flexShrink: 0, whiteSpace: 'nowrap' }}
                  >
                    {dmPreview.time}
                  </Text>
                </Box>
              )}
            </Box>
            {!optionsVisible && !unread && !selected && typingMember.length > 0 && (
              <Badge size="300" variant="Secondary" fill="Soft" radii="Pill" outlined>
                <TypingIndicator size="300" disableAnimation />
              </Badge>
            )}
            {!optionsVisible && unread && (
              <UnreadBadgeCenter>
                <UnreadBadge highlight={unread.highlight > 0} count={unread.total} />
              </UnreadBadgeCenter>
            )}
            {!optionsVisible && notificationMode !== RoomNotificationMode.Unset && (
              <Icon
                size="50"
                src={getRoomNotificationModeIcon(notificationMode)}
                aria-label={notificationMode}
              />
            )}
            {callMembers.length > 0 && (
              <Badge variant="Critical" fill="Solid" size="400">
                <Text as="span" size="L400" truncate>
                  {callMembers.length} Live
                </Text>
              </Badge>
            )}
          </Box>
        </NavItemContent>
      </NavLink>
      {optionsVisible && (
        <NavItemOptions>
          {selected && (callEmbed?.roomId === room.roomId || room.isCallRoom()) && (
            <CallChatToggle />
          )}
          <PopOut
            id={`menu-${room.roomId}`}
            aria-expanded={!!menuAnchor}
            anchor={menuAnchor}
            offset={menuAnchor?.width === 0 ? 0 : undefined}
            alignOffset={menuAnchor?.width === 0 ? 0 : -5}
            position="Bottom"
            align={menuAnchor?.width === 0 ? 'Start' : 'End'}
            content={
              <FocusTrap
                focusTrapOptions={{
                  initialFocus: false,
                  returnFocusOnDeactivate: false,
                  onDeactivate: () => setMenuAnchor(undefined),
                  clickOutsideDeactivates: true,
                  isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
                  isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
                  escapeDeactivates: stopPropagation,
                }}
              >
                <RoomNavItemMenu
                  room={room}
                  requestClose={() => setMenuAnchor(undefined)}
                  onRenameClick={() => setRenameDialog(true)}
                  notificationMode={notificationMode}
                />
              </FocusTrap>
            }
          >
            <IconButton
              onClick={handleOpenMenu}
              aria-pressed={!!menuAnchor}
              aria-controls={`menu-${room.roomId}`}
              aria-label="More Options"
              variant="Background"
              fill="None"
              size="300"
              radii="300"
            >
              <Icon size="50" src={Icons.VerticalDots} />
            </IconButton>
          </PopOut>
        </NavItemOptions>
      )}
      {renameDialog && <RenameRoomDialog room={room} onClose={() => setRenameDialog(false)} />}
    </NavItem>
  );
}
export const RoomNavItem = React.memo(RoomNavItem_);
