import React, { MouseEventHandler, forwardRef, useState } from 'react';
import { Badge, Icons, Menu, RectCords, Spinner, Text } from 'folds';
import { useTranslation } from 'react-i18next';
import { Room } from 'matrix-js-sdk';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { useSetting } from '../../../state/hooks/settings';
import { settingsAtom } from '../../../state/settings';
import { useRoomUnread } from '../../../state/hooks/unread';
import { roomToUnreadAtom } from '../../../state/room/roomToUnread';
import { usePowerLevelsContext } from '../../../hooks/usePowerLevels';
import { useRoomCreators } from '../../../hooks/useRoomCreators';
import { useRoomPermissions } from '../../../hooks/useRoomPermissions';
import { useRoomPinnedEvents } from '../../../hooks/useRoomPinnedEvents';
import { useRoomNavigate } from '../../../hooks/useRoomNavigate';
import { useSpaceOptionally } from '../../../hooks/useSpace';
import { useOpenRoomSettings } from '../../../state/hooks/roomSettings';
import {
  getRoomNotificationMode,
  useRoomsNotificationPreferencesContext,
} from '../../../hooks/useRoomsNotificationPreferences';
import { RoomNotificationModeSwitcher } from '../../../components/RoomNotificationSwitcher';
import { useBotPresets } from '../../bots/catalog';
import { findBotPresetForRoom } from '../../bots/room';
import { LeaveRoomPrompt } from '../../../components/leave-room-prompt';
import { InviteUserPrompt } from '../../../components/invite-user-prompt';
import { getCanonicalAliasOrRoomId, isRoomAlias } from '../../../utils/matrix';
import { getMatrixToRoom } from '../../../plugins/matrix-to';
import { getViaServers } from '../../../plugins/via-servers';
import { copyToClipboard } from '../../../utils/dom';
import { markAsRead } from '../../../utils/notifications';
import { JumpToTime } from '../jump-to-time';
import { ActionRow, ActionSectionLine, BotWidgetActionRow, RowChevron } from './RoomActions';
import * as css from './RoomActions.css';

type RoomActionsMenuProps = {
  room: Room;
  callView?: boolean;
  botControlRoom?: boolean;
  onPin: (cords: RectCords) => void;
  requestClose: () => void;
};

// Content of the room overflow (⋮) popout, on both desktop and mobile. The
// folds Menu `variant="Surface"` paints the deep Vojo input-field tone
// (#0d0e11 = Surface.Container — the exact fill of the chat message composer,
// see RoomView.css.ts). Nested sub-flows are the same as upstream:
// Notifications → the anchored RoomNotificationModeSwitcher PopOut; Pinned →
// the RoomPinMenu PopOut via onPin(cords); Invite/Jump/Leave → centered overlays.
export const RoomActionsMenu = forwardRef<HTMLDivElement, RoomActionsMenuProps>(
  ({ room, callView, botControlRoom, 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 pinnedEvents = useRoomPinnedEvents(room);
    const { navigateRoom } = useRoomNavigate();
    const openSettings = useOpenRoomSettings();
    const parentSpace = useSpaceOptionally();

    const bots = useBotPresets();
    const botPreset = botControlRoom ? findBotPresetForRoom(mx, room, bots) : undefined;

    const [invitePrompt, setInvitePrompt] = useState(false);
    const [promptJump, setPromptJump] = useState(false);
    const [promptLeave, setPromptLeave] = useState(false);

    const handleMarkAsRead = () => {
      markAsRead(mx, room.roomId, hideActivity);
      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();
    };

    return (
      <Menu ref={ref} variant="Surface" className={css.PopoutMenu}>
        {invitePrompt && (
          <InviteUserPrompt
            room={room}
            requestClose={() => {
              setInvitePrompt(false);
              requestClose();
            }}
          />
        )}
        {promptJump && (
          <JumpToTime
            onSubmit={(eventId) => {
              setPromptJump(false);
              navigateRoom(room.roomId, eventId);
              requestClose();
            }}
            onCancel={() => setPromptJump(false)}
          />
        )}
        {promptLeave && (
          <LeaveRoomPrompt
            roomId={room.roomId}
            onDone={requestClose}
            onCancel={() => setPromptLeave(false)}
          />
        )}

        <div className={css.PopoutGroup}>
          {botControlRoom && botPreset && (
            <BotWidgetActionRow
              roomId={room.roomId}
              botId={botPreset.id}
              requestClose={requestClose}
            />
          )}
          <ActionRow
            icon={Icons.CheckTwice}
            label={t('Room.mark_as_read')}
            onClick={handleMarkAsRead}
            disabled={!unread}
          />
          <RoomNotificationModeSwitcher roomId={room.roomId} value={notificationMode}>
            {(handleOpen, opened, changing) => (
              <ActionRow
                icon={Icons.Bell}
                label={t('Room.notifications')}
                onClick={handleOpen}
                ariaPressed={opened}
                ariaHasPopup
                trailing={changing ? <Spinner size="100" variant="Secondary" /> : <RowChevron />}
              />
            )}
          </RoomNotificationModeSwitcher>
          <ActionRow
            icon={Icons.Pin}
            label={t('Room.pinned_messages')}
            onClick={handleOpenPinned}
            ariaHasPopup
            trailing={
              <>
                {pinnedEvents.length > 0 && (
                  <Badge variant="Secondary" size="400" fill="Solid" radii="Pill">
                    <Text as="span" size="L400">
                      {pinnedEvents.length}
                    </Text>
                  </Badge>
                )}
                <RowChevron />
              </>
            }
          />
          <ActionRow icon={Icons.Link} label={t('Room.copy_link')} onClick={handleCopyLink} />
          <ActionRow
            icon={Icons.RecentClock}
            label={t('Room.jump_to_time')}
            onClick={() => setPromptJump(true)}
            ariaPressed={promptJump}
            ariaHasPopup
            trailing={<RowChevron />}
          />
          <ActionRow
            icon={Icons.Setting}
            label={t('Room.room_settings')}
            onClick={handleOpenSettings}
          />
        </div>

        {canInvite && !botControlRoom && (
          <>
            <ActionSectionLine />
            <div className={css.PopoutGroup}>
              <ActionRow
                icon={Icons.UserPlus}
                label={t('Room.invite')}
                onClick={() => setInvitePrompt(true)}
                accent="primary"
                ariaPressed={invitePrompt}
              />
            </div>
          </>
        )}

        <ActionSectionLine />
        <div className={css.PopoutGroup}>
          <ActionRow
            icon={Icons.ArrowGoLeft}
            label={t('Room.leave_room')}
            onClick={() => setPromptLeave(true)}
            accent="critical"
            disabled={callView}
            ariaPressed={promptLeave}
          />
        </div>
      </Menu>
    );
  }
);
