import { memo } from 'react';
import type { ReactElement } from 'react';
import { Pressable, StyleSheet, Text, View } from 'react-native';
import type { Message } from '@altricade/core';
import { OPTIMISTIC_SEQ } from '@altricade/core';
import { useTheme } from '@/theme';
import { spacing, radius, fontSize } from '@/theme';
import { MessageMeta } from './MessageMeta';
import type { SendStatus } from './MessageMeta';
import { ReplyQuote } from './ReplyQuote';
import { ForwardedHeader } from './ForwardedHeader';
import { Reactions } from './Reactions';
import { MediaContent } from './MediaContent';

export interface BubbleCallbacks {
  onLongPress: (message: Message) => void;
  onReplyPress: (messageId: string) => void;
  onToggleReaction: (message: Message, emoji: string) => void;
  onOpenViewer: (url: string, isVideo: boolean) => void;
  onPressUser: (username: string) => void;
}

interface Props extends BubbleCallbacks {
  message: Message;
  meId: string;
  isGroup: boolean;
  peerReadSeq: number;
  highlighted: boolean;
}

const statusOf = (message: Message, outgoing: boolean, peerReadSeq: number): SendStatus => {
  if (message.seq === OPTIMISTIC_SEQ) return 'pending';
  if (outgoing && peerReadSeq >= message.seq) return 'read';
  return 'sent';
};

const MessageBubbleInner = ({
  message,
  meId,
  isGroup,
  peerReadSeq,
  highlighted,
  onLongPress,
  onReplyPress,
  onToggleReaction,
  onOpenViewer,
  onPressUser,
}: Props): ReactElement => {
  const { colors } = useTheme();
  const outgoing = message.senderId === meId;
  const deleted = message.deletedAt !== null;
  const showSender = isGroup && !outgoing && !deleted;
  const bubbleColor = outgoing ? colors.bubbleOut : colors.bubbleIn;
  const textColor = outgoing ? colors.onAccent : colors.text;
  const hasText = message.content.length > 0 && !deleted;

  return (
    <View style={[styles.line, outgoing ? styles.lineOut : styles.lineIn]}>
      <Pressable
        onLongPress={() => {
          if (!deleted) {
            onLongPress(message);
          }
        }}
        delayLongPress={280}
        style={[
          styles.bubble,
          { backgroundColor: bubbleColor, borderColor: colors.border },
          outgoing ? styles.bubbleOut : styles.bubbleIn,
          highlighted && { borderColor: colors.accent, borderWidth: 2 },
        ]}
      >
        {message.forwarded ? (
          <ForwardedHeader origin={message.forwardedFrom} outgoing={outgoing} onPressUser={onPressUser} />
        ) : null}
        {showSender ? (
          <Text style={[styles.sender, { color: colors.accent }]} numberOfLines={1}>
            {message.sender.displayName}
          </Text>
        ) : null}
        {message.replyTo !== null ? (
          <ReplyQuote
            reply={message.replyTo}
            outgoing={outgoing}
            onPress={() => {
              if (message.replyTo !== null) {
                onReplyPress(message.replyTo.id);
              }
            }}
          />
        ) : null}
        {message.media !== null && !deleted ? (
          <View style={styles.media}>
            <MediaContent
              conversationId={message.conversationId}
              messageId={message.id}
              media={message.media}
              outgoing={outgoing}
              onOpenViewer={onOpenViewer}
            />
          </View>
        ) : null}
        {deleted ? (
          <Text style={[styles.deleted, { color: outgoing ? colors.onAccentMuted : colors.textFaint }]}>
            Message deleted
          </Text>
        ) : hasText ? (
          <Text style={[styles.text, { color: textColor }]}>{message.content}</Text>
        ) : null}
        <MessageMeta
          createdAt={message.createdAt}
          edited={message.editedAt !== null}
          outgoing={outgoing}
          status={statusOf(message, outgoing, peerReadSeq)}
        />
      </Pressable>
      {!deleted ? (
        <Reactions
          reactions={message.reactions}
          outgoing={outgoing}
          onToggle={(emoji) => {
            onToggleReaction(message, emoji);
          }}
        />
      ) : null}
    </View>
  );
};

export const MessageBubble = memo(MessageBubbleInner);

const styles = StyleSheet.create({
  line: { paddingHorizontal: spacing.md, marginVertical: 2, maxWidth: '100%' },
  lineOut: { alignItems: 'flex-end' },
  lineIn: { alignItems: 'flex-start' },
  bubble: {
    maxWidth: '82%',
    paddingHorizontal: spacing.md,
    paddingVertical: spacing.sm,
    borderRadius: radius.lg,
    gap: 2,
  },
  bubbleOut: { borderBottomRightRadius: radius.sm },
  bubbleIn: { borderBottomLeftRadius: radius.sm, borderWidth: StyleSheet.hairlineWidth },
  sender: { fontSize: fontSize.sm, fontWeight: '700', marginBottom: 1 },
  text: { fontSize: fontSize.base, lineHeight: 21 },
  deleted: { fontSize: fontSize.base, fontStyle: 'italic' },
  media: { marginBottom: 2 },
});
