import { useCallback, useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { apiChat, type ChatConversation, type ChatMessage, type ChatStudent } from '../api';
import { type StaffChatOpenDetail } from '../chatEvents';
import { useAuth } from '../auth/AuthContext';
import { onStaffChatMessage, playChatSound } from '../hooks/useStaffChatSocket';

export function ChatWidget() {
  const { staff } = useAuth();
  const [open, setOpen] = useState(false);
  const [query, setQuery] = useState('');
  const [students, setStudents] = useState<ChatStudent[]>([]);
  const [conversations, setConversations] = useState<ChatConversation[]>([]);
  const [active, setActive] = useState<ChatStudent | null>(null);
  const [messages, setMessages] = useState<ChatMessage[]>([]);
  const [draft, setDraft] = useState('');
  const [sending, setSending] = useState(false);
  const [pickerOpen, setPickerOpen] = useState(false);
  const [toast, setToast] = useState<{ title: string; body: string } | null>(null);
  const listRef = useRef<HTMLDivElement>(null);
  const activeRef = useRef<ChatStudent | null>(null);
  const openRef = useRef(false);

  useEffect(() => { activeRef.current = active; }, [active]);
  useEffect(() => { openRef.current = open; }, [open]);

  const scrollBottom = () => {
    requestAnimationFrame(() => {
      if (listRef.current) listRef.current.scrollTop = listRef.current.scrollHeight;
    });
  };

  const totalUnread = conversations.reduce((n, c) => n + (c.unread || 0), 0);

  const loadConversations = useCallback(async () => {
    const res = await apiChat.listConversations();
    setConversations(res.data);
    return res.data;
  }, []);

  const loadMessages = useCallback(async (studentRkId: number) => {
    const res = await apiChat.listMessages(studentRkId);
    setMessages(res.data);
    scrollBottom();
    await loadConversations();
  }, [loadConversations]);

  const searchStudents = useCallback(async (q: string) => {
    const res = await apiChat.searchStudents(q);
    setStudents(res.data);
  }, []);

  const showToast = (title: string, body: string) => {
    setToast({ title, body });
    setTimeout(() => setToast(null), 4500);
  };

  const handleIncoming = useCallback((msg: ChatMessage) => {
    const studentId = Number(msg.studentRkId);
    const current = activeRef.current;

    void loadConversations();

    if (msg.senderRole === 'student') {
      playChatSound();
      const preview = msg.body?.slice(0, 80) || 'Tin nhắn mới';
      if (!openRef.current || !current || Number(current.studentRkId) !== studentId) {
        showToast('Sinh viên nhắn tin', preview);
      }
    }

    if (current && Number(current.studentRkId) === studentId) {
      setMessages((prev) => {
        if (prev.some((m) => m.id === msg.id)) return prev;
        return [...prev, msg];
      });
      scrollBottom();
    }
  }, [loadConversations]);

  useEffect(() => {
    const off = onStaffChatMessage(handleIncoming);
    return () => { off(); };
  }, [handleIncoming]);

  useEffect(() => {
    const onOpen = (e: Event) => {
      const detail = (e as CustomEvent<StaffChatOpenDetail>).detail;
      if (!detail?.studentRkId) return;
      setOpen(true);
      setActive({
        studentRkId: detail.studentRkId,
        fullName: detail.fullName,
        studentCode: detail.studentCode,
        email: detail.email || '',
        online: false,
      });
      setPickerOpen(false);
      setQuery('');
      loadMessages(detail.studentRkId).catch(console.error);
    };
    window.addEventListener('staff-chat:open', onOpen);
    return () => window.removeEventListener('staff-chat:open', onOpen);
  }, [loadMessages]);

  useEffect(() => {
    if (!staff?.id) return;
    loadConversations().catch(console.error);
    const t = setInterval(() => loadConversations().catch(console.error), 5000);
    return () => clearInterval(t);
  }, [staff?.id, loadConversations]);

  const pickStudent = async (s: ChatStudent) => {
    setActive(s);
    setPickerOpen(false);
    setQuery('');
    await loadMessages(s.studentRkId);
  };

  const pickFromConversation = async (c: ChatConversation) => {
    await pickStudent({
      studentRkId: c.studentRkId,
      fullName: c.fullName,
      studentCode: c.studentCode,
      email: '',
      online: false,
    });
  };

  useEffect(() => {
    if (!open || !staff?.id) return;
    loadConversations().catch(console.error);
    searchStudents('').catch(console.error);
  }, [open, staff?.id, loadConversations, searchStudents]);

  const send = async () => {
    if (!active || !draft.trim()) return;
    setSending(true);
    try {
      const res = await apiChat.sendMessage(active.studentRkId, draft.trim());
      setMessages((prev) => [...prev, res.data]);
      setDraft('');
      scrollBottom();
      await loadConversations();
    } finally {
      setSending(false);
    }
  };

  if (!staff) return null;

  const dock = (
    <div className="chat-dock">
      {toast && (
        <div className="chat-toast" role="status">
          <strong>{toast.title}</strong>
          <span>{toast.body}</span>
        </div>
      )}
      {!open ? (
        <button type="button" className="chat-fab" onClick={() => setOpen(true)} title="Tin nhắn">
          💬
          {totalUnread > 0 && (
            <span className="chat-fab-badge">{totalUnread > 9 ? '9+' : totalUnread}</span>
          )}
        </button>
      ) : (
        <div className="chat-messenger">
          <header className="chat-messenger-head">
            <strong>Tin nhắn</strong>
            <div className="chat-head-actions">
              <button type="button" className="chat-icon-btn" onClick={() => setPickerOpen((v) => !v)} title="Tin mới">
                ✏️
              </button>
              <button type="button" className="chat-icon-btn" onClick={() => { setOpen(false); setActive(null); setPickerOpen(false); }} title="Đóng">
                ×
              </button>
            </div>
          </header>

          <div className="chat-messenger-body">
            <aside className="chat-sidebar">
              <div className="chat-sidebar-search">
                <input
                  placeholder="Tìm sinh viên..."
                  value={query}
                  onChange={(e) => {
                    setQuery(e.target.value);
                    searchStudents(e.target.value).catch(console.error);
                  }}
                  onFocus={() => setPickerOpen(true)}
                />
              </div>
              {pickerOpen && (
                <ul className="chat-picker-list">
                  {students.map((s) => (
                    <li key={s.studentRkId}>
                      <button type="button" onClick={() => pickStudent(s)}>
                        <span className="chat-conv-name">{s.fullName}</span>
                        <span className="chat-conv-meta">{s.studentCode}{s.online ? ' · online' : ''}</span>
                      </button>
                    </li>
                  ))}
                  {students.length === 0 && <li className="chat-empty-hint">Không tìm thấy sinh viên</li>}
                </ul>
              )}
              <ul className="chat-conv-list">
                {conversations.map((c) => (
                  <li key={c.studentRkId}>
                    <button
                      type="button"
                      className={active?.studentRkId === c.studentRkId ? 'active' : ''}
                      onClick={() => pickFromConversation(c)}
                    >
                      <div className="chat-conv-row">
                        <span className="chat-conv-name">{c.fullName}</span>
                        {c.unread > 0 && <span className="chat-conv-unread">{c.unread}</span>}
                      </div>
                      <span className="chat-conv-preview">{c.lastMessage || '—'}</span>
                      <span className="chat-conv-meta">{c.studentCode}</span>
                    </button>
                  </li>
                ))}
                {conversations.length === 0 && !pickerOpen && (
                  <li className="chat-empty-hint">Chưa có hội thoại — bấm ✏️ để nhắn sinh viên</li>
                )}
              </ul>
            </aside>

            <section className="chat-thread">
              {!active ? (
                <div className="chat-thread-empty">
                  <p>Chọn hội thoại bên trái hoặc tìm sinh viên để bắt đầu chat</p>
                </div>
              ) : (
                <>
                  <div className="chat-thread-head">
                    <div>
                      <strong>{active.fullName}</strong>
                      <div className="chat-sub">{active.studentCode}</div>
                    </div>
                  </div>
                  <div className="chat-messages" ref={listRef}>
                    {messages.map((m) => (
                      <div key={m.id} className={`chat-bubble chat-bubble--${m.senderRole}`}>
                        <div className="chat-bubble-body">{m.body}</div>
                        <div className="chat-bubble-time">
                          {new Date(m.createdAt).toLocaleString('vi-VN', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' })}
                        </div>
                      </div>
                    ))}
                    {messages.length === 0 && <div className="chat-empty-hint">Chưa có tin nhắn</div>}
                  </div>
                  <div className="chat-compose">
                    <input
                      placeholder="Nhập tin nhắn..."
                      value={draft}
                      onChange={(e) => setDraft(e.target.value)}
                      onKeyDown={(e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } }}
                    />
                    <button type="button" className="btn btn-primary btn-sm" disabled={sending || !draft.trim()} onClick={send}>
                      Gửi
                    </button>
                  </div>
                </>
              )}
            </section>
          </div>
        </div>
      )}
    </div>
  );

  return createPortal(dock, document.body);
}
