/* eslint-disable react/destructuring-assignment */
import React, { forwardRef, MouseEventHandler, useState } from 'react';
import {
  Avatar,
  Badge,
  Box,
  Icon,
  IconButton,
  Icons,
  Line,
  Menu,
  MenuItem,
  PopOut,
  RectCords,
  Spinner,
  Text,
  Tooltip,
  TooltipProvider,
  config,
  toRem,
} from 'folds';
import FocusTrap from 'focus-trap-react';
import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { useAtom, useAtomValue, useSetAtom } from 'jotai';
import { Room } from 'matrix-js-sdk';
import { PageHeader } from '../../components/page';
import { RoomAvatar, RoomIcon } from '../../components/room-avatar';
import { UserAvatar } from '../../components/user-avatar';
import { UseStateProvider } from '../../components/UseStateProvider';
import { BackRouteHandler } from '../../components/BackRouteHandler';
import { LeaveRoomPrompt } from '../../components/leave-room-prompt';
import { InviteUserPrompt } from '../../components/invite-user-prompt';
import { RoomNotificationModeSwitcher } from '../../components/RoomNotificationSwitcher';
import { ContainerColor } from '../../styles/ContainerColor.css';
import { ScreenSize, useScreenSizeContext } from '../../hooks/useScreenSize';
import { useStateEvent } from '../../hooks/useStateEvent';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
import { useIsOneOnOne, useRoom } from '../../hooks/useRoom';
import { useDmCallVisible } from '../../hooks/useDmCallVisible';
import { useRoomMemberCount } from '../../hooks/useRoomMemberCount';
import { Presence, useUserPresence } from '../../hooks/useUserPresence';
import { useRoomAvatar, useRoomName } from '../../hooks/useRoomMeta';
import { useRoomNavigate } from '../../hooks/useRoomNavigate';
import { useRoomUnread } from '../../state/hooks/unread';
import { useRoomPinnedEvents } from '../../hooks/useRoomPinnedEvents';
import { usePowerLevelsContext } from '../../hooks/usePowerLevels';
import { useRoomCreators } from '../../hooks/useRoomCreators';
import { useRoomPermissions } from '../../hooks/useRoomPermissions';
import { useSetting } from '../../state/hooks/settings';
import { useSpaceOptionally } from '../../hooks/useSpace';
import { useOpenRoomSettings } from '../../state/hooks/roomSettings';
import {
  getRoomNotificationMode,
  getRoomNotificationModeIcon,
  useRoomsNotificationPreferencesContext,
} from '../../hooks/useRoomsNotificationPreferences';
import { useLivekitSupport } from '../../hooks/useLivekitSupport';
import { useCallMembers, useCallSession } from '../../hooks/useCall';
import { useSwitchOrStartDmCall } from '../../hooks/useSwitchOrStartDmCall';
import { useOpenUserRoomProfile } from '../../state/hooks/userRoomProfile';
import { settingsAtom } from '../../state/settings';
import { callEmbedAtom } from '../../state/callEmbed';
import { searchModalAtom } from '../../state/searchModal';
import { roomToUnreadAtom } from '../../state/room/roomToUnread';
import { RoomSettingsPage } from '../../state/roomSettings';
import { StateEvent } from '../../../types/matrix/room';
import {
  getCanonicalAliasOrRoomId,
  getMxIdLocalPart,
  getMxIdServer,
  guessDmRoomUserId,
  isRoomAlias,
  mxcUrlToHttp,
} from '../../utils/matrix';
import { copyToClipboard } from '../../utils/dom';
import { stopPropagation } from '../../utils/keyboard';
import { markAsRead } from '../../utils/notifications';
import { getMatrixToRoom } from '../../plugins/matrix-to';
import { getViaServers } from '../../plugins/via-servers';
import { useBotPresets } from '../bots/catalog';
import { findBotPresetForRoom, isCatalogBotControlRoom } from '../bots/room';
import { botFailedAtomFamily, botShowChatAtomFamily } from '../bots/botExperienceState';
import { getBotPath } from '../../pages/pathUtils';
import { JumpToTime } from './jump-to-time';
import { RoomPinMenu } from './room-pin-menu';
import * as css from './RoomViewHeaderDm.css';

// Single bot-aware menu item rendered at the top of RoomMenu when the
// current room is a Vojo bot control DM. Reads `botFailedAtomFamily` to
// label correctly («Retry widget» when a prior load failed, «Show widget»
// otherwise) and clears both atoms on click.
//
// IMPORTANT: this menu surfaces in BOTH `/bots/:botId` (chat-fallback) and
// `/direct/:roomId` (regular DM that happens to be a bot's control room).
// In the second case clearing the atoms alone is invisible — the user is
// not on the route that observes them. We navigate to `/bots/:botId` so
// the BotShell actually mounts.
function BotShowWidgetMenuItem({
  roomId,
  botId,
  requestClose,
}: {
  roomId: string;
  botId: string;
  requestClose: () => void;
}) {
  const { t } = useTranslation();
  const navigate = useNavigate();
  const setShowChat = useSetAtom(botShowChatAtomFamily(roomId));
  const [failed, setFailed] = useAtom(botFailedAtomFamily(roomId));
  const handleClick = () => {
    setFailed(false);
    setShowChat(false);
    navigate(getBotPath(botId));
    requestClose();
  };
  return (
    <MenuItem
      onClick={handleClick}
      size="300"
      after={<Icon size="100" src={Icons.Terminal} />}
      radii="300"
    >
      <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
        {t(failed ? 'Bots.retry_widget' : 'Bots.show_widget')}
      </Text>
    </MenuItem>
  );
}

type RoomMenuProps = {
  room: Room;
  callView?: boolean;
  // When true the room is a Vojo bot control DM rendered in chat-fallback
  // mode. The menu prepends a «Show widget / Retry widget» item so the
  // user can return to BotShell without hunting for an overlay button.
  // Other items stay standard — bots in chat-fallback should look like
  // normal rooms beyond that one affordance.
  botControlRoom?: boolean;
  onSearch: () => void;
  onPin: (cords: RectCords) => void;
  requestClose: () => void;
};
const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(
  ({ room, callView, botControlRoom, onSearch, onPin, requestClose }, ref) => {
    const { t } = useTranslation();
    const mx = useMatrixClient();
    const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
    const unread = useRoomUnread(room.roomId, roomToUnreadAtom);
    const powerLevels = usePowerLevelsContext();
    const creators = useRoomCreators(room);
    const permissions = useRoomPermissions(creators, powerLevels);
    const canInvite = permissions.action('invite', mx.getSafeUserId());
    const notificationPreferences = useRoomsNotificationPreferencesContext();
    const notificationMode = getRoomNotificationMode(notificationPreferences, room.roomId);
    const { navigateRoom } = useRoomNavigate();
    const pinnedEvents = useRoomPinnedEvents(room);
    const openSettings = useOpenRoomSettings();
    const parentSpace = useSpaceOptionally();
    // Look up the matching bot preset only when this menu IS the bot
    // variant. The lookup walks the preset list once; cheap. Returns
    // undefined for non-bot rooms — we won't render the menu item.
    const bots = useBotPresets();
    const botPreset = botControlRoom ? findBotPresetForRoom(mx, room, bots) : undefined;

    const [invitePrompt, setInvitePrompt] = useState(false);

    const handleMarkAsRead = () => {
      markAsRead(mx, room.roomId, hideActivity);
      requestClose();
    };
    const handleSearch = () => {
      onSearch();
      requestClose();
    };
    const handleOpenPinned: MouseEventHandler<HTMLButtonElement> = (evt) => {
      onPin(evt.currentTarget.getBoundingClientRect());
      requestClose();
    };
    const handleCopyLink = () => {
      const roomIdOrAlias = getCanonicalAliasOrRoomId(mx, room.roomId);
      const viaServers = isRoomAlias(roomIdOrAlias) ? undefined : getViaServers(room);
      copyToClipboard(getMatrixToRoom(roomIdOrAlias, viaServers));
      requestClose();
    };
    const handleOpenSettings = () => {
      openSettings(room.roomId, parentSpace?.roomId);
      requestClose();
    };
    const handleInvite = () => {
      setInvitePrompt(true);
    };

    return (
      <Menu ref={ref} style={{ maxWidth: toRem(220), width: '100vw' }}>
        {invitePrompt && (
          <InviteUserPrompt
            room={room}
            requestClose={() => {
              setInvitePrompt(false);
              requestClose();
            }}
          />
        )}
        {botControlRoom && botPreset && (
          <>
            <Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
              <BotShowWidgetMenuItem
                roomId={room.roomId}
                botId={botPreset.id}
                requestClose={requestClose}
              />
            </Box>
            <Line variant="Surface" size="300" />
          </>
        )}
        <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>
              {t('Room.mark_as_read')}
            </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>
                  {t('Room.notifications')}
                </Text>
              </MenuItem>
            )}
          </RoomNotificationModeSwitcher>
        </Box>
        <Line variant="Surface" size="300" />
        <Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
          <MenuItem
            onClick={handleSearch}
            size="300"
            after={<Icon size="100" src={Icons.Search} />}
            radii="300"
          >
            <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
              {t('Room.search')}
            </Text>
          </MenuItem>
          <MenuItem
            onClick={handleOpenPinned}
            size="300"
            after={
              <Box gap="100" alignItems="Center">
                {pinnedEvents.length > 0 && (
                  <Badge variant="Secondary" size="400" fill="Solid" radii="Pill">
                    <Text as="span" size="L400">
                      {pinnedEvents.length}
                    </Text>
                  </Badge>
                )}
                <Icon size="100" src={Icons.Pin} />
              </Box>
            }
            radii="300"
          >
            <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
              {t('Room.pinned_messages')}
            </Text>
          </MenuItem>
          {canInvite && (
            <MenuItem
              onClick={handleInvite}
              variant="Primary"
              fill="None"
              size="300"
              after={<Icon size="100" src={Icons.UserPlus} />}
              radii="300"
              aria-pressed={invitePrompt}
            >
              <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                {t('Room.invite')}
              </Text>
            </MenuItem>
          )}
          <MenuItem
            onClick={handleCopyLink}
            size="300"
            after={<Icon size="100" src={Icons.Link} />}
            radii="300"
          >
            <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
              {t('Room.copy_link')}
            </Text>
          </MenuItem>
          <MenuItem
            onClick={handleOpenSettings}
            size="300"
            after={<Icon size="100" src={Icons.Setting} />}
            radii="300"
          >
            <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
              {t('Room.room_settings')}
            </Text>
          </MenuItem>
          <UseStateProvider initial={false}>
            {(promptJump, setPromptJump) => (
              <>
                <MenuItem
                  onClick={() => setPromptJump(true)}
                  size="300"
                  after={<Icon size="100" src={Icons.RecentClock} />}
                  radii="300"
                  aria-pressed={promptJump}
                >
                  <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                    {t('Room.jump_to_time')}
                  </Text>
                </MenuItem>
                {promptJump && (
                  <JumpToTime
                    onSubmit={(eventId) => {
                      setPromptJump(false);
                      navigateRoom(room.roomId, eventId);
                      requestClose();
                    }}
                    onCancel={() => setPromptJump(false)}
                  />
                )}
              </>
            )}
          </UseStateProvider>
        </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}
                  disabled={callView}
                >
                  <Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
                    {t('Room.leave_room')}
                  </Text>
                </MenuItem>
                {promptLeave && (
                  <LeaveRoomPrompt
                    roomId={room.roomId}
                    onDone={requestClose}
                    onCancel={() => setPromptLeave(false)}
                  />
                )}
              </>
            )}
          </UseStateProvider>
        </Box>
      </Menu>
    );
  }
);

function DmCallButton({ room }: { room: Room }) {
  const { t } = useTranslation();
  const mx = useMatrixClient();
  const switchOrStartDmCall = useSwitchOrStartDmCall();
  const livekitSupported = useLivekitSupport();
  const session = useCallSession(room);
  const members = useCallMembers(room, session);
  const currentEmbed = useAtomValue(callEmbedAtom);

  const myUserId = mx.getSafeUserId();
  const inCallHere = currentEmbed?.roomId === room.roomId;
  if (inCallHere) return null;

  const ongoingByOthers = members.length > 0 && !members.some((m) => m.userId === myUserId);
  const disabled = !livekitSupported;
  let tooltipText: string;
  if (!livekitSupported) tooltipText = t('Call.unavailable');
  else if (ongoingByOthers) tooltipText = t('Call.join');
  else tooltipText = t('Call.start');

  const handleClick = () => {
    if (disabled) return;
    switchOrStartDmCall(room.roomId).catch((err: unknown) => {
      // eslint-disable-next-line no-console
      console.warn('[call] header switch/start failed', err);
    });
  };

  return (
    <TooltipProvider
      position="Bottom"
      offset={4}
      tooltip={
        <Tooltip>
          <Text>{tooltipText}</Text>
        </Tooltip>
      }
    >
      {(triggerRef) => (
        <IconButton
          fill="None"
          ref={triggerRef}
          onClick={handleClick}
          disabled={disabled}
          aria-label={tooltipText}
        >
          <Icon size="400" src={Icons.Phone} />
        </IconButton>
      )}
    </TooltipProvider>
  );
}

export function RoomViewHeaderDm({ callView }: { callView?: boolean }) {
  const { t } = useTranslation();
  const mx = useMatrixClient();
  const useAuthentication = useMediaAuthentication();
  const screenSize = useScreenSizeContext();
  const room = useRoom();
  const isOneOnOne = useIsOneOnOne();
  const isMobile = screenSize === ScreenSize.Mobile;

  // Call surface visibility is shared with the `Call` button inside
  // `UserRoomProfile` via `useDmCallVisible` — the hook captures all
  // four gates (1:1 + m.direct + !bridged + !bot-control) so the two
  // call-entry surfaces can't drift apart. Header-specific extras
  // here: hide in callView (we're already showing CallView). The
  // hook itself documents the call-lifecycle reasoning.
  const dmCallVisible = useDmCallVisible(room);
  const callButtonVisible = !callView && dmCallVisible;

  // `isBotControlRoom` is also passed down to `RoomMenu` to gate the
  // bot-config menu item — kept here as its own derivation because
  // the hook above is purpose-built for the call gate, not for
  // generic «is this a bot DM?» queries.
  const bots = useBotPresets();
  const isBotControlRoom = isCatalogBotControlRoom(mx, room, bots);

  const encryptionEvent = useStateEvent(room, StateEvent.RoomEncryption);
  const encryptedRoom = !!encryptionEvent;

  const avatarMxc = useRoomAvatar(room, isOneOnOne);
  const name = useRoomName(room);
  const memberCount = useRoomMemberCount(room);
  const avatarUrl = avatarMxc
    ? mxcUrlToHttp(mx, avatarMxc, useAuthentication, 96, 96, 'crop') ?? undefined
    : undefined;

  // Peer details for 1:1 chrome — handle (`local:server`, no `@` prefix —
  // we drop the sigil to keep the line lighter) and tap-to-open user-room-
  // profile sheet. `guessDmRoomUserId` returns the oldest-joined non-self
  // member, but its last fallback is `myUserId` itself — drop that case so
  // we never render the room as if I were the peer (avatar trigger would
  // open my own profile, handle would show my mxid).
  //
  // The server segment is kept so cross-server users with identical
  // local-parts (e.g. `alex:vojo.chat` vs `alex:other.org`) stay visually
  // distinct.
  const myUserId = mx.getSafeUserId();
  const peerCandidate = isOneOnOne ? guessDmRoomUserId(room, myUserId) : undefined;
  const peerUserId = peerCandidate && peerCandidate !== myUserId ? peerCandidate : undefined;
  const peerLocal = peerUserId ? getMxIdLocalPart(peerUserId) : undefined;
  const peerServer = peerUserId ? getMxIdServer(peerUserId) : undefined;
  const handle =
    peerLocal && peerServer ? `${peerLocal}:${peerServer}` : peerUserId?.replace(/^@/, '');

  // `useUserPresence` is a no-op when `peerUserId` is undefined (group rooms,
  // unresolved peer) — it just returns undefined. Real presence comes from
  // matrix-js-sdk `User` events; the hook subscribes to Presence /
  // CurrentlyActive / LastPresenceTs and re-renders. We only show «в сети»
  // when the peer is actively online; offline / unavailable hides the line.
  const peerPresence = useUserPresence(peerUserId ?? '');
  const peerOnline = !!peerUserId && peerPresence?.presence === Presence.Online;

  const [peopleDrawer, setPeopleDrawer] = useSetting(settingsAtom, 'isPeopleDrawer');

  const [menuAnchor, setMenuAnchor] = useState<RectCords>();
  const [pinMenuAnchor, setPinMenuAnchor] = useState<RectCords>();
  const setSearchOpen = useSetAtom(searchModalAtom);
  const openUserRoomProfile = useOpenUserRoomProfile();
  const parentSpace = useSpaceOptionally();
  const openSettings = useOpenRoomSettings();

  const handleOpenMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
    setMenuAnchor(evt.currentTarget.getBoundingClientRect());
  };
  const handleSearch = () => {
    // P4 routes in-room search through the global cmd+K modal — there is no
    // /direct/{roomId}/search/ page yet (see desired_features.md §26). The
    // modal lets the user pick the target room manually.
    setSearchOpen(true);
  };
  const handlePeerProfile: MouseEventHandler<HTMLButtonElement> = (evt) => {
    if (!peerUserId) return;
    openUserRoomProfile(
      room.roomId,
      parentSpace?.roomId,
      peerUserId,
      evt.currentTarget.getBoundingClientRect(),
      'Bottom'
    );
  };
  const handleMemberToggle = () => {
    if (callView) {
      openSettings(room.roomId, parentSpace?.roomId, RoomSettingsPage.MembersPage);
      return;
    }
    setPeopleDrawer(!peopleDrawer);
  };

  const avatarNode = (
    <Avatar size="300">
      {isOneOnOne && peerUserId ? (
        <UserAvatar
          userId={peerUserId}
          src={avatarUrl}
          alt={name}
          renderFallback={() => <Icon size="200" src={Icons.User} filled />}
        />
      ) : (
        <RoomAvatar
          roomId={room.roomId}
          src={avatarUrl}
          alt={name}
          renderFallback={() => (
            <RoomIcon size="200" joinRule={room.getJoinRule()} roomType={room.getType()} />
          )}
        />
      )}
    </Avatar>
  );

  const e2eeChip = encryptedRoom && (
    <Text as="span" size="T200" className={css.E2eeChip}>
      <Icon src={Icons.Lock} filled className={css.E2eeIcon} />
      {t('Room.encrypted_short')}
    </Text>
  );

  // Single subline format, identical on mobile + desktop:
  //   1:1   →  «@local:server» (mono) + (peer online ? « · в сети» : nothing)
  //   group →  «N members»
  // Title row carries the room name and the «онлайн» presence tag (1:1
  // peer only, when actually Online via `useUserPresence`). Subline carries
  // the muted identifier (handle for 1:1, member-count for groups) and,
  // for 1:1 rooms, the e2ee chip — moved out of the title row so the chip
  // sits near the technical identifier rather than the human name.
  const showOnlineTag = isOneOnOne && peerOnline;
  const showHandlePart = isOneOnOne && !!handle;
  const showGroupSubline = !isOneOnOne;

  // Title block (name row + subline) — identical for 1:1 and group; the
  // difference is purely in the wrapper (clickable identity button for
  // 1:1, plain row for groups).
  const titleBlock = (
    <Box grow="Yes" direction="Column" style={{ minWidth: 0 }}>
      <div className={css.TitleRow}>
        <Text size={isMobile ? 'H5' : 'H4'} truncate className={css.RoomName}>
          {name}
        </Text>
        {showOnlineTag && (
          <Text as="span" size="T200" className={css.OnlineTag}>
            {t('Room.status_online')}
          </Text>
        )}
      </div>
      {showHandlePart && (
        <Text as="span" size="T200" className={css.Subline}>
          <span className={css.SublineMuted}>{handle}</span>
          {e2eeChip}
        </Text>
      )}
      {showGroupSubline && (
        <Text as="span" size="T200" className={css.Subline}>
          <span className={css.SublineMuted}>
            {t('Room.members_count', {
              count: memberCount,
              formattedCount: memberCount,
            })}
          </span>
          {e2eeChip}
        </Text>
      )}
    </Box>
  );

  // For 1:1 rooms wrap the avatar AND title in a single button so a tap
  // anywhere on the user identity (avatar, name, handle, online tag)
  // opens the user-room-profile sheet — one tab stop, one focus
  // outline, single popout anchor. Groups keep the avatar non-clickable
  // and the title as a plain row.
  const identityArea =
    isOneOnOne && peerUserId ? (
      <button
        type="button"
        className={css.PeerIdentityTrigger}
        onClick={handlePeerProfile}
        aria-label={t('Room.open_profile_of', { name })}
      >
        {avatarNode}
        {titleBlock}
      </button>
    ) : (
      <>
        <span className={css.PeerAvatarStatic}>{avatarNode}</span>
        {titleBlock}
      </>
    );

  return (
    <PageHeader
      className={`${ContainerColor({ variant: 'SurfaceVariant' })} ${css.HeaderShell}`}
      balance={isMobile}
    >
      {/* `gap="200"` (= S200 = 8px) keeps the avatar's right side flush with
          the same `S200` left/top/bottom clearance the header gives — using
          the default `gap="300"` (12px) made the avatar→title spacing
          visibly looser than the rest of its surround. */}
      <Box grow="Yes" alignItems="Center" gap="200">
        {isMobile && (
          <BackRouteHandler>
            {(onBack) => (
              <Box shrink="No" alignItems="Center">
                <IconButton fill="None" onClick={onBack} aria-label={t('Room.close')}>
                  <Icon src={Icons.ChevronLeft} />
                </IconButton>
              </Box>
            )}
          </BackRouteHandler>
        )}

        {identityArea}

        <Box shrink="No" alignItems="Center">
          {callButtonVisible && <DmCallButton room={room} />}

          {/* Member toggle — desktop-only. Visible in two cases:
              - group rooms (>2 members): toggles the members drawer.
              - call rooms (`callView=true`), regardless of size: routes to
                Room Settings → Members so 1:1 call rooms can still reach
                the member list (drawer doesn't render in callView).
              For non-call 1:1 rooms it stays hidden because the avatar tap
              already opens the peer profile sheet. */}
          {(callView || !isOneOnOne) && screenSize === ScreenSize.Desktop && (
            <TooltipProvider
              position="Bottom"
              offset={4}
              tooltip={
                <Tooltip>
                  {callView ? (
                    <Text>{t('Room.members')}</Text>
                  ) : (
                    <Text>{peopleDrawer ? t('Room.hide_members') : t('Room.show_members')}</Text>
                  )}
                </Tooltip>
              }
            >
              {(triggerRef) => (
                <IconButton fill="None" ref={triggerRef} onClick={handleMemberToggle}>
                  <Icon size="400" src={Icons.User} />
                </IconButton>
              )}
            </TooltipProvider>
          )}

          <TooltipProvider
            position="Bottom"
            align="End"
            offset={4}
            tooltip={
              <Tooltip>
                <Text>{t('Room.more_options')}</Text>
              </Tooltip>
            }
          >
            {(triggerRef) => (
              <IconButton
                fill="None"
                onClick={handleOpenMenu}
                ref={triggerRef}
                aria-pressed={!!menuAnchor}
              >
                <Icon size="400" src={Icons.VerticalDots} filled={!!menuAnchor} />
              </IconButton>
            )}
          </TooltipProvider>

          <PopOut
            anchor={menuAnchor}
            position="Bottom"
            align="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,
                }}
              >
                <RoomMenu
                  room={room}
                  callView={callView}
                  botControlRoom={isBotControlRoom}
                  onSearch={handleSearch}
                  onPin={(cords) => setPinMenuAnchor(cords)}
                  requestClose={() => setMenuAnchor(undefined)}
                />
              </FocusTrap>
            }
          />

          <PopOut
            anchor={pinMenuAnchor}
            position="Bottom"
            align="End"
            content={
              <FocusTrap
                focusTrapOptions={{
                  initialFocus: false,
                  returnFocusOnDeactivate: false,
                  onDeactivate: () => setPinMenuAnchor(undefined),
                  clickOutsideDeactivates: true,
                  isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown',
                  isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp',
                  escapeDeactivates: stopPropagation,
                }}
              >
                <RoomPinMenu room={room} requestClose={() => setPinMenuAnchor(undefined)} />
              </FocusTrap>
            }
          />
        </Box>
      </Box>
    </PageHeader>
  );
}
