"use client";

import { useEffect, useState, useRef } from "react";
import { getChannelMessages, Message, getAccessToken } from "@/lib/api";
import { connectSocket } from "@/lib/socket";
import { MessageActions } from "./MessageActions";
import { ReactionBar } from "./ReactionBar";

interface MessageListProps {
  channelId: string;
  onReply?: (message: Message) => void;
  onEdit?: (message: Message) => void;
  onDelete?: (message: Message) => void;
}

function getMessageText(msg: Message): string {
  return msg.text || msg.content || "";
}

function getUserId(msg: Message): string {
  return msg.userId || msg.user_id || "";
}

function getDisplayName(msg: Message): string {
  return msg.user?.name || msg.user?.display_name || msg.user?.displayName || msg.user?.email || "Unknown";
}

function getTimestamp(msg: Message): string {
  return msg.createdAt || msg.created_at || msg.ts || "";
}

// Extract reactions from message object if present
function getReactions(msg: any): { emoji: string; count: number; userIds?: string[] }[] {
  if (msg.reactions && Array.isArray(msg.reactions)) {
    return msg.reactions.map((r: any) => ({
      emoji: r.emoji || r.emoji_code || r.name,
      count: r.count || r.user_ids?.length || 1,
      userIds: r.user_ids || r.users?.map((u: any) => u.id || u) || [],
    }));
  }
  return [];
}

export function MessageList({ channelId, onReply, onEdit, onDelete }: MessageListProps) {
  const [messages, setMessages] = useState<Message[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const [hoveredMsg, setHoveredMsg] = useState<string | null>(null);
  const [refreshKey, setRefreshKey] = useState(0);
  const bottomRef = useRef<HTMLDivElement>(null);

  // Load messages from API
  useEffect(() => {
    setLoading(true);
    setError("");
    getChannelMessages(channelId)
      .then((data) => {
        setMessages(data.messages || []);
      })
      .catch((err) => {
        console.error("Failed to load messages:", err);
        setError("Failed to load messages");
      })
      .finally(() => setLoading(false));
  }, [channelId, refreshKey]);

  // Connect WebSocket for real-time messages + reactions
  useEffect(() => {
    const token = getAccessToken();
    if (!token) return;

    const socket = connectSocket(token);

    const onNewMessage = (msg: Message) => {
      const msgChannelId = msg.channelId || msg.channel_id;
      if (msgChannelId === channelId) {
        setMessages((prev) => {
          if (prev.some((m) => m.id === msg.id)) return prev;
          return [...prev, msg];
        });
      }
    };

    const onReactionUpdate = (data: { messageId?: string; message_id?: string }) => {
      const messageId = data?.messageId || data?.message_id;
      if (messageId) {
        setRefreshKey((k) => k + 1);
      }
    };

    const onThreadReply = (data: { thread_root_id?: string; channelId?: string; channel_id?: string }) => {
      // Refresh messages when a thread reply comes in so thread counts update
      setRefreshKey((k) => k + 1);
    };

    socket.on("message:new", onNewMessage);
    socket.on("reaction:added", onReactionUpdate);
    socket.on("reaction:removed", onReactionUpdate);
    socket.on("thread:new_reply", onThreadReply);

    return () => {
      socket.off("message:new", onNewMessage);
      socket.off("reaction:added", onReactionUpdate);
      socket.off("reaction:removed", onReactionUpdate);
      socket.off("thread:new_reply", onThreadReply);
    };
  }, [channelId]);

  // Scroll to bottom when messages change
  useEffect(() => {
    bottomRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [messages]);

  const formatTime = (iso: string) => {
    try {
      const d = new Date(iso);
      return d.toLocaleString("en-US", {
        month: "short",
        day: "numeric",
        hour: "numeric",
        minute: "2-digit",
      });
    } catch {
      return iso;
    }
  };

  const getAvatarLetter = (msg: Message) => {
    const name = getDisplayName(msg);
    return name[0]?.toUpperCase() || "U";
  };

  if (loading) {
    return (
      <div className="h-full flex items-center justify-center text-gray-400 animate-pulse">
        Loading messages...
      </div>
    );
  }

  if (error) {
    return (
      <div className="h-full flex items-center justify-center text-red-500 text-sm">
        {error}
      </div>
    );
  }

  return (
    <div className="h-full overflow-y-auto px-4 py-4">
      <div className="border-b border-gray-100 pb-4 mb-4">
        <h2 className="text-lg font-bold text-gray-800">
          Welcome to the channel
        </h2>
        <p className="text-sm text-gray-400">This is the beginning of this channel.</p>
      </div>

      {messages.length === 0 ? (
        <div className="text-gray-400 text-sm text-center py-8">
          No messages yet. Be the first to say something!
        </div>
      ) : (
        <ul className="space-y-1">
          {messages.map((msg, idx) => {
            const prevMsg = idx > 0 ? messages[idx - 1] : null;
            const showHeader =
              !prevMsg ||
              getUserId(prevMsg) !== getUserId(msg) ||
              new Date(getTimestamp(msg)).getTime() -
                new Date(getTimestamp(prevMsg)).getTime() >
                5 * 60 * 1000;
            const reactions = getReactions(msg);
            const showReactions = reactions.length > 0 || hoveredMsg === msg.id;
            return (
              <li
                key={msg.id}
                className={`flex gap-3 ${showHeader ? "mt-4 pt-2" : "mt-0.5"} group relative hover:bg-gray-50 rounded px-2 py-1`}
                onMouseEnter={() => setHoveredMsg(msg.id)}
                onMouseLeave={() => setHoveredMsg(null)}
              >
                <div className="w-9 h-9 rounded-md bg-slack-purple text-white flex items-center justify-center text-sm font-bold flex-shrink-0">
                  {getAvatarLetter(msg)}
                </div>
                <div className="flex-1 min-w-0">
                  {showHeader && (
                    <div className="flex items-baseline gap-2">
                      <span className="font-bold text-sm text-gray-900">
                        {getDisplayName(msg)}
                      </span>
                      <span className="text-xs text-gray-400">
                        {formatTime(getTimestamp(msg))}
                      </span>
                    </div>
                  )}
                  <p className="text-sm text-gray-800 whitespace-pre-wrap break-words">
                    {getMessageText(msg)}
                  </p>

                  {/* Reactions row - shows ReactionBar on hover or when reactions exist */}
                  {showReactions && (
                    <div className="mt-1">
                      <ReactionBar
                        messageId={msg.id}
                        reactions={reactions}
                        onReactionsChange={() => setRefreshKey((k) => k + 1)}
                      />
                    </div>
                  )}
                </div>

                {/* Floating actions on hover */}
                {hoveredMsg === msg.id && (
                  <div className="absolute right-2 -top-3 z-10">
                    <MessageActions
                      message={msg}
                      channelId={channelId}
                      onReply={onReply}
                      onEdit={onEdit}
                      onDelete={onDelete}
                    />
                  </div>
                )}
              </li>
            );
          })}
        </ul>
      )}
      <div ref={bottomRef} />
    </div>
  );
}