import { isDifferentDay } from "../../utils/helpers";
import { DateSeparator, MessageBubble } from "./MessageBubble";
import {
  MessageList as MessageListType,
  ThreadParticipant,
} from "../../../src/api/types/models";
import { Loader2, ArrowDown } from "lucide-react";
import {
  useState,
  useRef,
  useEffect,
  forwardRef,
  ForwardedRef,
  useImperativeHandle,
} from "react";

// Message List component
const MessageList = forwardRef(
  (
    {
      messages,
      isLoading,
      isFetching,
      userId,
      teamUserIds,
      viewerIsStore = false,
      onReply,
      onDelete,
      onScroll,
      otherParticipant,
    }: {
      messages: MessageListType[];
      isLoading: boolean;
      isFetching: boolean;
      userId: string | undefined;
      // Senders on the store team. Only treated as "our side" when the VIEWER
      // is store-side (viewerIsStore) — otherwise a customer would wrongly see
      // the store's staff messages on their own (right) side.
      teamUserIds?: readonly string[];
      // True when the current viewer is on this thread's store team. Gates all
      // team-grouping so the customer view stays "my messages right, store left".
      viewerIsStore?: boolean;
      onReply: (message: MessageListType) => void;
      onDelete?: (messageId: string) => void;
      onScroll?: (event: React.UIEvent<HTMLDivElement>) => void;
      otherParticipant: ThreadParticipant | undefined;
    },
    ref: ForwardedRef<{
      scrollToBottom: () => void;
      getContainer: () => HTMLDivElement | null;
    }>
  ) => {
    const [highlightedMessageId, setHighlightedMessageId] = useState<
      string | null
    >(null);
    const messageRefs = useRef<Record<string, HTMLDivElement | null>>({});
    const [showScrollButton, setShowScrollButton] = useState(false);
    const containerRef = useRef<HTMLDivElement>(null);

    // Expose methods to parent component
    useImperativeHandle(ref, () => ({
      scrollToBottom: () => {
        if (containerRef.current) {
          containerRef.current.scrollTo({
            top: containerRef.current.scrollHeight,
          });
        }
      },
      getContainer: () => containerRef.current,
    }));

    // Handle scroll events to show/hide the scroll button
    useEffect(() => {
      const container = containerRef.current;
      if (!container) return;

      const handleScroll = (e: Event) => {
        // Show button when scrolled up more than 300px from bottom
        const isScrolledUp =
          container.scrollHeight -
            container.scrollTop -
            container.clientHeight >
          300;
        setShowScrollButton(isScrolledUp);

        // Call parent's onScroll handler if provided
        if (onScroll && e instanceof UIEvent) {
          onScroll(e as unknown as React.UIEvent<HTMLDivElement>);
        }
      };

      container.addEventListener("scroll", handleScroll);
      return () => container.removeEventListener("scroll", handleScroll);
    }, [onScroll]);

    const scrollToBottom = () => {
      if (containerRef.current) {
        containerRef.current.scrollTo({
          top: containerRef.current.scrollHeight + 100,
          behavior: "smooth",
        });
      }
    };

    if (isLoading && !messages.length) {
      return (
        <p className="text-GRAY text-center">درحال بارگذاری پیام‌ها...</p>
      );
    }

    if (messages.length === 0) {
      return (
        <p className="text-GRAY text-center">
          هنوز پیامی ارسال نشده. مکالمه را شروع کنید!
        </p>
      );
    }

    // Handle reply click to scroll to original message
    const handleReplyClick = (replyToId: string) => {
      const targetMessage = messages.find((m) => m.id === replyToId);
      if (targetMessage) {
        // Reset the highlighted message ID first to ensure the animation can trigger again
        setHighlightedMessageId(null);

        // Use setTimeout to ensure the state update has processed
        setTimeout(() => {
          // Then set the highlighted message ID
          setHighlightedMessageId(replyToId);

          // Scroll to the message
          const messageElement = messageRefs.current[replyToId];
          if (messageElement) {
            messageElement.scrollIntoView({
              behavior: "smooth",
              block: "center",
            });
          }
        }, 300);
      }
    };

    return (
      <div
        className="flex flex-col pt-[60px] relative h-[calc(100vh-64px)] overflow-auto px-2 pb-8"
        style={{ scrollbarWidth: "inherit" }}
        ref={containerRef}
        onScroll={onScroll}
      >
        {isFetching && (
          <div className="flex items-center justify-center py-2">
            <Loader2 className="w-4 h-4 animate-spin" />
          </div>
        )}
        {messages.map((message, index) => (
          <div
            key={message.id || index}
            ref={(el) => {
              if (message.id) {
                messageRefs.current[message.id] = el;
              }
            }}
          >
            {/* Date separator - show when day changes between messages */}
            {(index === 0 ||
              isDifferentDay(
                message.createdAt || "",
                messages[index - 1]?.createdAt
              )) && <DateSeparator date={message.createdAt || ""} />}

            {/* Message bubble */}
            <MessageBubble
              otherParticipant={otherParticipant}
              message={message}
              isCurrentUser={
                message.sender === userId ||
                (viewerIsStore &&
                  !!message.sender &&
                  !!teamUserIds?.includes(message.sender))
              }
              isCoworker={
                viewerIsStore &&
                message.sender !== userId &&
                !!message.sender &&
                !!teamUserIds?.includes(message.sender)
              }
              onReply={onReply}
              onDelete={onDelete}
              replyToMessageContent={message.replyContent || ""}
              onReplyClick={handleReplyClick}
              isHighlighted={highlightedMessageId === message.id}
            />
          </div>
        ))}

        {/* Floating scroll to bottom button with animation */}
        <div
          className={`fixed bottom-16 right-4 z-30 transition-all duration-300 ${
            showScrollButton
              ? "opacity-100 translate-y-0"
              : "opacity-0 translate-y-10 pointer-events-none"
          }`}
        >
          <button
            onClick={scrollToBottom}
            className="w-8 h-8 bg-primary text-WHITE rounded-full flex items-center justify-center shadow-lg hover:bg-primary/90 transition-all z-10"
            aria-label="رفتن به پایین"
          >
            <ArrowDown className="w-4 h-4" />
          </button>
        </div>
      </div>
    );
  }
);

// Add display name
MessageList.displayName = "MessageList";

export default MessageList;
