import React, { ReactNode } from 'react';
import { Box, Text } from 'folds';
import { MatrixEvent, Room } from 'matrix-js-sdk';
import { useTranslation } from 'react-i18next';
import {
  ChannelLayout,
  ChannelMessageAvatar,
  StreamLayout,
  Time,
  Username,
  UsernameBold,
} from '../../../components/message';
import { Event } from './Message';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { useDotColor } from '../../../hooks/useDotColor';
import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
import { getMemberDisplayName } from '../../../utils/room';
import { getMxIdLocalPart } from '../../../utils/matrix';

export type SyslineMessageProps = {
  room: Room;
  mEvent: MatrixEvent;
  // Pre-rendered body — already includes any sender names / interpolation
  // the per-type renderer wants to show. The sysline bubble adds no extra
  // header or icon, so the body is the only visible content.
  body: ReactNode;
  highlight: boolean;
  canDelete?: boolean;
  hideReadReceipts?: boolean;
  showDeveloperTools?: boolean;
  streamRailStart?: boolean;
  streamRailEnd?: boolean;
  layout?: 'stream' | 'channel';
  channelHeaderInBubble?: boolean;
  // Spread onto Event wrapper (data-message-item / data-message-id) so the
  // virtual paginator can locate the row.
  [dataAttr: `data-${string}`]: string | number | undefined;
};

export function SyslineMessage({
  room,
  mEvent,
  body,
  highlight,
  canDelete,
  hideReadReceipts,
  showDeveloperTools,
  streamRailStart,
  streamRailEnd,
  layout = 'stream',
  channelHeaderInBubble,
  ...rest
}: SyslineMessageProps) {
  const { t } = useTranslation();
  const mx = useMatrixClient();
  const isMobile = useScreenSizeContext() === ScreenSize.Mobile;
  const dot = useDotColor(room, mEvent, true, hideReadReceipts);

  const senderId = mEvent.getSender() ?? '';
  const isOwnMessage = !!mx.getUserId() && senderId === mx.getUserId();
  const peerBg = !isOwnMessage;
  const senderName =
    getMemberDisplayName(room, senderId) || getMxIdLocalPart(senderId) || senderId;

  const bubbleBody = (
    <Box style={{ minWidth: 0 }}>
      <Text as="span" size="T300" priority="300">
        {body}
      </Text>
    </Box>
  );

  return (
    <Event
      key={mEvent.getId()}
      room={room}
      mEvent={mEvent}
      highlight={highlight}
      canDelete={canDelete}
      hideReadReceipts={hideReadReceipts}
      showDeveloperTools={showDeveloperTools}
      {...rest}
    >
      {layout === 'channel' ? (
        <ChannelLayout
          isOwn={isOwnMessage}
          headerInBubble={channelHeaderInBubble}
          avatar={
            <ChannelMessageAvatar
              room={room}
              senderId={senderId}
              senderDisplayName={senderName}
            />
          }
          header={
            <>
              <Username as="span">
                <Text as="span" size={channelHeaderInBubble ? 'T200' : 'T400'} truncate>
                  <UsernameBold>
                    {isOwnMessage ? t('Direct.message_me_label') : senderName}
                  </UsernameBold>
                </Text>
              </Username>
              <Time ts={mEvent.getTs()} compact size="T200" priority="300" />
            </>
          }
        >
          {bubbleBody}
        </ChannelLayout>
      ) : (
        <StreamLayout
          time={<Time ts={mEvent.getTs()} compact />}
          dotColor={dot.color}
          dotOpacity={dot.opacity}
          isOwn={isOwnMessage}
          peerBg={peerBg}
          compact={isMobile}
          railStart={streamRailStart}
          railEnd={streamRailEnd}
        >
          {bubbleBody}
        </StreamLayout>
      )}
    </Event>
  );
}
