import { addToast, cn } from '@heroui/react';
import { type Message as BaseMessage, useMujian } from '@mujian/js-sdk/react';
import React, { type MouseEventHandler } from 'react';
import { mjChatCls } from '@/utils/cls';
import { EditActions } from './components/EditActions';
import { MessageActions } from './components/MessageActions';
import { MessageBubble } from './components/MessageBubble';

export type MessageItemProps = {
  message: BaseMessage;
  originalMessage: BaseMessage;

  index: number;
  avatar: string;
  name: string;
  isLastMsg?: boolean;
  isFirstMsg?: boolean;

  onRegenerate?: () => Promise<void>;
  onContinue?: () => Promise<void>;
  onDelete: (messageId: string) => Promise<void>;
  onEdit: (messageId: string, content: string) => Promise<void>;
  onSwipe: (messageId: string, swipeId: number) => Promise<void>;
  sendMessage?: (message: string) => Promise<void>;
};

// Add comparison function for React.memo
const arePropsEqual = (
  prevProps: MessageItemProps,
  nextProps: MessageItemProps,
) => {
  // 如果 swipes 长度不同，直接返回 false
  if (prevProps.message.swipes?.length !== nextProps.message.swipes?.length) {
    return false;
  }
  // 如果 swipes 内容不同，直接返回 false
  if (
    prevProps.message.swipes?.some(
      (swipe, index) => swipe !== nextProps.message.swipes[index],
    )
  ) {
    return false;
  }

  // 其他属性比较
  return (
    prevProps.avatar === nextProps.avatar &&
    prevProps.message.content === nextProps.message.content &&
    prevProps.message.role === nextProps.message.role &&
    prevProps.message.isStreaming === nextProps.message.isStreaming &&
    prevProps.name === nextProps.name &&
    prevProps.isLastMsg === nextProps.isLastMsg &&
    prevProps.message.sendAt === nextProps.message.sendAt &&
    prevProps.message.activeSwipeId === nextProps.message.activeSwipeId &&
    prevProps.message.id === nextProps.message.id &&
    prevProps.index === nextProps.index
  );
};

export const MessageItem = React.memo((props: MessageItemProps) => {
  const {
    message,
    originalMessage,

    // index,
    // avatar,
    // name,
    isLastMsg,
    isFirstMsg,
    onRegenerate,
    onContinue,
    onDelete,
    onEdit,
    onSwipe,
  } = props;
  const {
    id,

    role,
    isStreaming,

    content,
    swipes = [],
    activeSwipeId,

    // sendAt,
  } = message;
  const isUser = role === 'user';

  const messageRef = React.useRef<HTMLDivElement>(null); // 使用 useRef 获取当前组件的引用
  const [isEditing, setIsEditing] = React.useState(false); // State to toggle edit mode
  const [editedMessage, setEditedMessage] = React.useState(content);
  const mujian = useMujian();

  const renderedMessage = isUser ? content : swipes[activeSwipeId];

  // 滚动到消息可见位置的通用函数
  const scrollMessageIntoView = (
    alignToBlock: ScrollLogicalPosition = 'end',
    behavior: ScrollBehavior = 'instant',
  ) => {
    if (messageRef.current) {
      messageRef.current.scrollIntoView({
        behavior: behavior,
        block: alignToBlock,
      });
    }
  };

  const handleSaveEdit = async () => {
    if (id && activeSwipeId !== undefined) {
      await onEdit(id, editedMessage);
      setIsEditing(false);

      setTimeout(() => scrollMessageIntoView('end', 'smooth'), 100);
    }
  };

  const handleCopy = async () => {
    try {
      await mujian.utils.clipboard.writeText(originalMessage.content);
      addToast({
        color: 'success',
        description: '复制成功',
        timeout: 2000,
      });
    } catch (error) {
      console.error(error);
      addToast({
        description: '复制失败，请重试。',
      });
    }
  };

  // Separate function to handle message deletion
  const handleDeleteMessage = async () => {
    if (id) {
      onDelete(id);
    }
  };
  // console.log("content", index, content);

  // 确保 currentSwipeId 在有效范围内
  const validSwipeId = Math.min(Math.max(0, activeSwipeId), swipes.length - 1);

  const handleSwipe = async (direction: 'prev' | 'next') => {
    if (swipes.length <= 1) return;

    // 简化计算逻辑，直接使用模运算确保能够循环浏览所有页面
    const newSwipeId =
      direction === 'prev'
        ? (activeSwipeId - 1 + swipes.length) % swipes.length
        : (activeSwipeId + 1) % swipes.length;

    await onSwipe(id, newSwipeId);

    scrollMessageIntoView();
  };

  // Stop propagation for message text clicks
  const handleMessageTextClick: MouseEventHandler<HTMLDivElement> = (e) => {
    e.stopPropagation();
  };

  const handleEditButtonClick = async () => {
    setIsEditing(true);
    if (isUser) {
      setEditedMessage(originalMessage.content);
    } else {
      setEditedMessage(originalMessage.swipes[validSwipeId]);
    }
  };

  return (
    <div
      key={`message-${activeSwipeId}`}
      ref={messageRef} // 将 ref 绑定到根容器
      className={mjChatCls(
        ['msg-item-wrapper'],
        cn('grid items-end gap-2 mb-2 w-full grid-cols-[32px_1fr_32px]'),
      )}
      onContextMenu={(event) => {
        // 按ctrl点击时打印ID
        if (event.ctrlKey) {
          event.preventDefault();
          console.log('Official Chat Message ID:', id);
        }
      }}
    >
      <MessageBubble
        message={message}
        isUser={isUser}
        isEditing={isEditing}
        editedMessage={editedMessage}
        onEditChange={setEditedMessage}
        onCopyClick={handleCopy}
        isStreaming={isStreaming}
        currentMessage={renderedMessage}
        onEditButtonClick={handleEditButtonClick}
        onDelete={handleDeleteMessage}
        onEditAreaShow={() => scrollMessageIntoView()}
      />
      <EditActions
        isUser={isUser}
        isEditing={isEditing}
        onSaveEdit={handleSaveEdit}
        onCancelEdit={() => {
          setIsEditing(false);
          setEditedMessage(
            isUser
              ? originalMessage.content
              : originalMessage.swipes[activeSwipeId],
          );
          // 滚动到消息位置
          setTimeout(() => scrollMessageIntoView('end', 'smooth'), 100);
        }}
      />
      <MessageActions
        message={message}
        isUser={isUser}
        isLastMsg={Boolean(isLastMsg)}
        isFirstMsg={Boolean(isFirstMsg)}
        isStreaming={isStreaming}
        isEditing={isEditing}
        swipes={swipes}
        activeSwipeId={activeSwipeId}
        onRegenerate={onRegenerate}
        onContinue={onContinue}
        onEditButtonClick={handleEditButtonClick}
        onCopyClick={handleCopy}
        onSwipe={handleSwipe}
        onMessageTextClick={handleMessageTextClick}
        onDelete={handleDeleteMessage}
      />
    </div>
  );
}, arePropsEqual);

MessageItem.displayName = 'Message';
