import { useCallback, useEffect, useRef, useState } from "react";
import type { Channel } from "@/types/Channel";
import type { Message } from "@/types/Message";
import { getChannels, getMessages, getCurrentUsername } from "@/api";
import { ChannelSidebar } from "@/components/ChannelSidebar";
import { MessageItem } from "@/components/MessageItem";
import { ComposeBox } from "@/components/ComposeBox";

export default function App() {
  const [channels, setChannels] = useState<Channel[]>([]);
  const [activeChannelId, setActiveChannelId] = useState<string | null>(null);
  const [messages, setMessages] = useState<Message[]>([]);
  const [replyTo, setReplyTo] = useState<string | null>(null);
  const scrollRef = useRef<HTMLDivElement>(null);
  const prevMsgCountRef = useRef(0);
  const activeChannelRef = useRef(activeChannelId);

  // Keep ref in sync
  activeChannelRef.current = activeChannelId;

  const loadChannels = useCallback(async () => {
    const chs = await getChannels();
    setChannels(chs);
    // Auto-select first channel only if none selected
    setActiveChannelId((prev) => (prev ? prev : chs[0]?.id ?? null));
  }, []);

  const loadMessages = useCallback(async () => {
    const channelId = activeChannelRef.current;
    if (!channelId) return;
    try {
      const msgs = await getMessages(channelId);
      // Only update if we're still on the same channel (prevent race)
      if (activeChannelRef.current === channelId) {
        setMessages(msgs);
      }
    } catch {
      // Silently ignore fetch errors during polling
    }
  }, []);

  // Initial channel load
  useEffect(() => {
    loadChannels();
  }, [loadChannels]);

  // Load messages on channel switch
  useEffect(() => {
    setMessages([]); // Clear immediately on switch
    setReplyTo(null);
    prevMsgCountRef.current = 0;
    loadMessages();
  }, [activeChannelId, loadMessages]);

  // Auto-scroll only when NEW messages arrive (not on every poll)
  useEffect(() => {
    if (messages.length > prevMsgCountRef.current && scrollRef.current) {
      scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
    }
    prevMsgCountRef.current = messages.length;
  }, [messages]);

  // Poll until WebSocket (S5)
  useEffect(() => {
    const interval = setInterval(loadMessages, 3000);
    return () => clearInterval(interval);
  }, [loadMessages]);

  const messagesById = new Map(messages.map((m) => [m.id, m]));
  const activeChannel = channels.find((c) => c.id === activeChannelId);
  const _currentUser = getCurrentUsername();

  return (
    <div className="flex h-full">
      <ChannelSidebar
        channels={channels}
        activeId={activeChannelId}
        onSelect={setActiveChannelId}
        onChannelCreated={loadChannels}
      />

      <div className="flex-1 flex flex-col min-w-0">
        {/* Channel header */}
        <div className="px-4 py-2 border-b border-border flex items-center gap-2">
          {activeChannel ? (
            <>
              <span className="text-muted-foreground">#</span>
              <span className="font-bold text-[14px]">
                {activeChannel.name}
              </span>
              {activeChannel.description && (
                <span className="text-[11px] text-muted-foreground ml-2">
                  {activeChannel.description}
                </span>
              )}
              <span className="ml-auto text-[10px] text-muted-foreground tabular-nums">
                {messages.length} msg
              </span>
            </>
          ) : (
            <span className="text-muted-foreground text-[12px]">
              select a channel
            </span>
          )}
        </div>

        {/* Messages */}
        <div ref={scrollRef} className="flex-1 overflow-y-auto">
          {messages.length === 0 && activeChannelId && (
            <div className="flex items-center justify-center h-full text-muted-foreground text-[12px]">
              no messages yet
            </div>
          )}
          {messages.map((msg) => (
            <MessageItem
              key={msg.id}
              message={msg}
              replyTarget={
                msg.reply_to ? messagesById.get(msg.reply_to) : undefined
              }
              onReply={setReplyTo}
            />
          ))}
        </div>

        {/* Compose — key forces reset on channel switch */}
        {activeChannelId && (
          <ComposeBox
            key={activeChannelId}
            channelId={activeChannelId}
            replyTo={replyTo}
            onClearReply={() => setReplyTo(null)}
            onMessageSent={loadMessages}
          />
        )}
      </div>
    </div>
  );
}
