// Dawn-evolved user profile card. Replaces the legacy chip-strip
// layout (large Message + Call buttons → horizontal chip strip)
// with a denser, IDE-style information card:
//
//   • Hero       — large gradient avatar, display name, monospaced
//                  handle, presence + last-seen, optional e2ee badge.
//   • Info rows  — Fleet-style attribute table: id / server / role /
//                  mutual chats. Each row has a trailing affordance
//                  (popout menu) when there's something useful to do.
//   • Actions    — single «Написать» chip in group rooms only
//                  (1:1 → user is already in the conversation),
//                  plus the three-dot moderation menu (`OptionsChip`).
//   • Alerts     — banner cards for ignored / banned / kicked /
//                  invited states. Same matrix-js-sdk source as
//                  before, just rendered after the redesigned
//                  surface.

import React from 'react';
import { Box } from 'folds';
import { useNavigate } from 'react-router-dom';
import { UserHero } from './UserHero';
import { IdRow, MutualRoomsRow, RoleRow, ServerRow } from './UserInfoRows';
import { mxcUrlToHttp } from '../../utils/matrix';
import { getMemberAvatarMxc, getMemberDisplayName } from '../../utils/room';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
import { usePowerLevels } from '../../hooks/usePowerLevels';
import { useIsOneOnOne, useRoom } from '../../hooks/useRoom';
import { useUserPresence } from '../../hooks/useUserPresence';
import { useStateEvent } from '../../hooks/useStateEvent';
import { IgnoredUserAlert, UserActionsMenu } from './UserChips';
import { useCloseUserRoomProfile } from '../../state/hooks/userRoomProfile';
import { UserBanAlert, UserInviteAlert, UserKickAlert } from './UserModeration';
import { useIgnoredUsers } from '../../hooks/useIgnoredUsers';
import { useMembership } from '../../hooks/useMembership';
import { Membership, StateEvent } from '../../../types/matrix/room';
import { useRoomCreators } from '../../hooks/useRoomCreators';
import { useRoomPermissions } from '../../hooks/useRoomPermissions';
import { useMemberPowerCompare } from '../../hooks/useMemberPowerCompare';
import { useGetMemberPowerTag } from '../../hooks/useMemberPowerTag';
import { getDirectCreatePath, withSearchParam } from '../../pages/pathUtils';
import { DirectCreateSearchParams } from '../../pages/paths';
import * as css from './styles.css';

type UserRoomProfileProps = {
  userId: string;
  onAvatarClick?: () => void;
  // Desktop side-pane only — forwarded straight to `UserHero` so the
  // hero avatar can render in its inline-expanded mode while the
  // rest of the card stays in flow. Mobile leaves this `undefined`
  // and keeps using the full-rail avatar swap inside
  // `RoomViewProfilePanel`.
  avatarExpanded?: boolean;
};

export function UserRoomProfile({ userId, onAvatarClick, avatarExpanded }: UserRoomProfileProps) {
  const mx = useMatrixClient();
  const useAuthentication = useMediaAuthentication();
  const navigate = useNavigate();
  const closeUserRoomProfile = useCloseUserRoomProfile();
  const ignoredUsers = useIgnoredUsers();
  const ignored = ignoredUsers.includes(userId);

  const room = useRoom();
  const powerLevels = usePowerLevels(room);
  const creators = useRoomCreators(room);

  const permissions = useRoomPermissions(creators, powerLevels);
  const { hasMorePower } = useMemberPowerCompare(creators, powerLevels);
  const getMemberPowerTag = useGetMemberPowerTag(room, creators, powerLevels);

  const myUserId = mx.getSafeUserId();
  const creator = creators.has(userId);

  const canKickUser = permissions.action('kick', myUserId) && hasMorePower(myUserId, userId);
  const canBanUser = permissions.action('ban', myUserId) && hasMorePower(myUserId, userId);
  const canUnban = permissions.action('ban', myUserId);
  const canInvite = permissions.action('invite', myUserId);

  const member = room.getMember(userId);
  const membership = useMembership(room, userId);

  const displayName = getMemberDisplayName(room, userId);
  const avatarMxc = getMemberAvatarMxc(room, userId);
  // The collapsed HeroAvatar renders at 96px CSS (user-profile/styles.css.ts).
  // A `crop` thumbnail can't fix retina sharpness here: Synapse only
  // pre-generates 32px and 96px CROP thumbnails by default, so any `crop`
  // request > 96 just returns the 96px one — upscaled and pixelated on a 2–3×
  // display. `scale` thumbnails go up to 320/640/800, so we request a 320 scale:
  // sharp on retina yet ~10× smaller than the full-resolution original (which
  // the SDK returns when no dimensions are passed, and which made the hero
  // visibly progressive-load on open). `UserAvatar` forces `object-fit: cover`,
  // so a non-square scale thumbnail still fills the circle. The full-res
  // original is reserved for the expanded tile + tap-to-zoom fullview below.
  const avatarUrl =
    (avatarMxc && mxcUrlToHttp(mx, avatarMxc, useAuthentication, 320, 320, 'scale')) ?? undefined;
  // Full-resolution original for the desktop side-pane expanded (~340px) tile —
  // a 96px thumbnail would upscale and pixelate when blown up. Only fetched
  // when the avatar is expanded (UserHero swaps to this src then).
  const avatarUrlExpanded =
    (avatarMxc && mxcUrlToHttp(mx, avatarMxc, useAuthentication)) ?? undefined;

  // Pass the raw SDK presence through. `UserHero` already guards on
  // `lastActiveTs > 0` before formatting the last-seen line, so the
  // «1970» misread is suppressed there. Filtering at this layer
  // would also drop the *online* signal for users whose
  // `lastActiveTs` happens to be 0 on a fresh sync — they'd lose
  // their green dot and «онлайн» tag for no good reason.
  const presence = useUserPresence(userId);

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

  const isOneOnOne = useIsOneOnOne();
  const showStartDmChip = !isOneOnOne && userId !== myUserId;

  // Power-tag label resolution: the room's power-level tags map a
  // numeric pl to a localised role name (e.g. «admin», «moderator»,
  // «member»). The hook handles the creator → «Создатель» override
  // internally via `useRoomCreatorsTag`, so we just take the tag's
  // `.name` and display it. The raw `pl N` number is intentionally
  // not surfaced — it's Matrix protocol jargon that's redundant
  // with the role label for end users.
  const tag = getMemberPowerTag(userId);
  const roleLabel = tag.name;

  const handleMessage = () => {
    closeUserRoomProfile();
    const params: DirectCreateSearchParams = { userId };
    navigate(withSearchParam(getDirectCreatePath(), params));
  };

  return (
    <Box direction="Column" gap="500" className={css.CardRoot}>
      {/* Top-right action menu — absolute-positioned so it floats
          above the hero without claiming a layout row. Hosts every
          imperative action (Write / Block / Mod). On mobile the
          rail is short enough that a bottom actions row scrolled
          off-screen; floating it at a fixed corner of the card
          fixes that. Suppressed on self-profile since none of the
          items are meaningful there. */}
      {userId !== myUserId && (
        <div className={css.CardActionsAnchor}>
          <UserActionsMenu
            userId={userId}
            showStartDm={showStartDmChip}
            onStartDm={handleMessage}
            canKick={canKickUser && membership === Membership.Join}
            canBan={canBanUser && membership !== Membership.Ban}
            canInvite={canInvite && membership === Membership.Leave}
          />
        </div>
      )}

      <UserHero
        userId={userId}
        displayName={displayName}
        avatarUrl={avatarUrl}
        avatarUrlExpanded={avatarUrlExpanded}
        presence={presence}
        encrypted={encrypted}
        onAvatarClick={onAvatarClick}
        avatarExpanded={avatarExpanded}
      />

      <div className={css.InfoSection}>
        <IdRow userId={userId} />
        <ServerRow userId={userId} />
        {userId !== myUserId && <RoleRow roleLabel={roleLabel} emphasis={creator} />}
        {userId !== myUserId && <MutualRoomsRow userId={userId} />}
      </div>

      {ignored && <IgnoredUserAlert />}
      {member && membership === Membership.Ban && (
        <UserBanAlert
          userId={userId}
          reason={member.events.member?.getContent().reason}
          canUnban={canUnban}
          bannedBy={member.events.member?.getSender()}
          ts={member.events.member?.getTs()}
        />
      )}
      {member &&
        membership === Membership.Leave &&
        member.events.member &&
        member.events.member.getSender() !== userId && (
          <UserKickAlert
            reason={member.events.member?.getContent().reason}
            kickedBy={member.events.member?.getSender()}
            ts={member.events.member?.getTs()}
          />
        )}
      {member && membership === Membership.Invite && (
        <UserInviteAlert
          userId={userId}
          reason={member.events.member?.getContent().reason}
          canKick={canKickUser}
          invitedBy={member.events.member?.getSender()}
          ts={member.events.member?.getTs()}
        />
      )}
    </Box>
  );
}
