import { useState, useEffect, useRef, useCallback } from 'react';
import Message from './Message.jsx';
import MessageInput from './MessageInput.jsx';
import { api } from '../utils/api.js';
import { useAuth } from '../contexts/AuthContext.jsx';
import { useToast } from '../contexts/ToastContext.jsx';
import { useSocket } from '../contexts/SocketContext.jsx';
import './ChatWindow.css';
import GroupInfoModal from './GroupInfoModal.jsx';

export default function ChatWindow({ group, onBack, onGroupUpdated, onDirectMessage, onlineUserIds = new Set() }) {
  const { user: currentUser } = useAuth();
  const { socket } = useSocket();
  const { toast } = useToast();

  const [messages, setMessages] = useState([]);
  const [loading, setLoading] = useState(false);
  const [hasMore, setHasMore] = useState(false);
  const [typing, setTyping] = useState([]);
  const [iconGroupInfo, setIconGroupInfo] = useState('');
  const [avatarColors, setAvatarColors] = useState({ public: '#1a73e8', dm: '#a142f4' });
  const [showInfo, setShowInfo] = useState(false);
  const [replyTo, setReplyTo] = useState(null);
  const [isMobile, setIsMobile] = useState(window.innerWidth < 768);

  const messagesEndRef = useRef(null);
  const messagesContainerRef = useRef(null);
  const typingTimers = useRef({});

  useEffect(() => {
    const onResize = () => setIsMobile(window.innerWidth < 768);
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, []);

  useEffect(() => {
    api.getSettings().then(({ settings }) => {
      setIconGroupInfo(settings.icon_groupinfo || '');
      setAvatarColors({ public: settings.color_avatar_public || '#1a73e8', dm: settings.color_avatar_dm || '#a142f4' });
    }).catch(() => {});
    const handler = () => api.getSettings().then(({ settings }) => {
      setIconGroupInfo(settings.icon_groupinfo || '');
      setAvatarColors({ public: settings.color_avatar_public || '#1a73e8', dm: settings.color_avatar_dm || '#a142f4' });
    }).catch(() => {});
    window.addEventListener('jama:settings-updated', handler);
    window.addEventListener('jama:settings-changed', handler);
    return () => {
      window.removeEventListener('jama:settings-updated', handler);
      window.removeEventListener('jama:settings-changed', handler);
    };
  }, []);

  const scrollToBottom = useCallback((smooth = false) => {
    messagesEndRef.current?.scrollIntoView({ behavior: smooth ? 'smooth' : 'auto' });
  }, []);

  useEffect(() => {
    if (!group) { setMessages([]); return; }
    setMessages([]);
    setHasMore(false);
    setLoading(true);
    api.getMessages(group.id)
      .then(({ messages }) => {
        setMessages(messages);
        setHasMore(messages.length >= 50);
        setTimeout(() => scrollToBottom(), 50);
      })
      .catch(e => toast(e.message, 'error'))
      .finally(() => setLoading(false));
  }, [group?.id]);

  // Socket events
  useEffect(() => {
    if (!socket || !group) return;

    const handleNew = (msg) => {
      if (msg.group_id !== group.id) return;
      setMessages(prev => {
        if (prev.find(m => m.id === msg.id)) return prev;
        return [...prev, msg];
      });
      setTimeout(() => scrollToBottom(true), 50);
    };

    const handleDeleted = ({ messageId }) => {
      setMessages(prev => prev.map(m =>
        m.id === messageId ? { ...m, is_deleted: 1, content: null, image_url: null } : m
      ));
    };

    const handleReaction = ({ messageId, reactions }) => {
      setMessages(prev => prev.map(m =>
        m.id === messageId ? { ...m, reactions } : m
      ));
    };

    const handleTypingStart = ({ userId: tid, user: tu }) => {
      if (tid === currentUser?.id) return;
      setTyping(prev => prev.find(t => t.userId === tid)
        ? prev
        : [...prev, { userId: tid, name: tu?.display_name || tu?.name || 'Someone' }]);
      if (typingTimers.current[tid]) clearTimeout(typingTimers.current[tid]);
      typingTimers.current[tid] = setTimeout(() => {
        setTyping(prev => prev.filter(t => t.userId !== tid));
      }, 4000);
    };

    const handleTypingStop = ({ userId: tid }) => {
      clearTimeout(typingTimers.current[tid]);
      setTyping(prev => prev.filter(t => t.userId !== tid));
    };

    const handleGroupUpdated = (updatedGroup) => {
      if (updatedGroup.id === group.id) onGroupUpdated?.();
    };

    socket.on('message:new', handleNew);
    socket.on('message:deleted', handleDeleted);
    socket.on('reaction:updated', handleReaction);
    socket.on('typing:start', handleTypingStart);
    socket.on('typing:stop', handleTypingStop);
    socket.on('group:updated', handleGroupUpdated);

    return () => {
      socket.off('message:new', handleNew);
      socket.off('message:deleted', handleDeleted);
      socket.off('reaction:updated', handleReaction);
      socket.off('typing:start', handleTypingStart);
      socket.off('typing:stop', handleTypingStop);
      socket.off('group:updated', handleGroupUpdated);
    };
  }, [socket, group?.id, currentUser?.id]);

  const handleLoadMore = async () => {
    if (!hasMore || loading || messages.length === 0) return;
    const container = messagesContainerRef.current;
    const prevScrollHeight = container?.scrollHeight || 0;
    setLoading(true);
    try {
      const oldest = messages[0];
      const { messages: older } = await api.getMessages(group.id, oldest.id);
      setMessages(prev => [...older, ...prev]);
      setHasMore(older.length >= 50);
      requestAnimationFrame(() => {
        if (container) container.scrollTop = container.scrollHeight - prevScrollHeight;
      });
    } catch (e) {
      toast(e.message, 'error');
    } finally {
      setLoading(false);
    }
  };

  const handleSend = async ({ content, imageFile, linkPreview, emojiOnly }) => {
    if ((!content?.trim() && !imageFile) || !group) return;
    const replyToId = replyTo?.id || null;
    setReplyTo(null);
    try {
      if (imageFile) {
        await api.uploadImage(group.id, imageFile, { replyToId, content: content?.trim() || '' });
      } else {
        await api.sendMessage(group.id, { content: content.trim(), replyToId, linkPreview, emojiOnly });
      }
    } catch (e) {
      toast(e.message || 'Failed to send', 'error');
    }
  };

  const handleDelete = async (msgId) => {
    try {
      await api.deleteMessage(msgId);
    } catch (e) {
      toast(e.message || 'Could not delete', 'error');
    }
  };

  const handleReact = async (msgId, emoji) => {
    try {
      await api.toggleReaction(msgId, emoji);
    } catch (e) {
      toast(e.message || 'Could not react', 'error');
    }
  };

  const handleReply = (msg) => {
    setReplyTo(msg);
  };

  const handleDirectMessage = (dmGroup) => {
    onDirectMessage?.(dmGroup);
  };

  if (!group) {
    return (
      <div className="chat-window empty">
        <div className="empty-state">
          <div className="empty-icon">
            <svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5">
              <path strokeLinecap="round" strokeLinejoin="round" d="M7.5 8.25h9m-9 3H12m-9.75 1.51c0 1.6 1.123 2.994 2.707 3.227 1.129.166 2.27.293 3.423.379.35.026.67.21.865.501L12 21l2.755-4.133a1.14 1.14 0 0 1 .865-.501 48.172 48.172 0 0 0 3.423-.379c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0 0 12 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018Z" />
            </svg>
          </div>
          <h3>Select a conversation</h3>
          <p>Choose a channel or direct message to start chatting</p>
        </div>
      </div>
    );
  }

  const isDirect = !!group.is_direct;
  const peerName = group.peer_display_name
    ? <>{group.peer_display_name}<span className="chat-header-real-name"> ({group.peer_real_name})</span></>
    : group.peer_real_name || group.name;
  const isOnline = isDirect && group.peer_id && (onlineUserIds instanceof Set ? onlineUserIds.has(Number(group.peer_id)) : false);

  return (
    <>
    <div className="chat-window">
      {/* Header */}
      <div className="chat-header">
        {isMobile && onBack && (
          <button className="btn-icon" onClick={onBack} style={{ marginRight: 4 }}>
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
              <polyline points="15 18 9 12 15 6"/>
            </svg>
          </button>
        )}

        {isDirect && group.peer_avatar && !group.is_managed ? (
          <div style={{ position: 'relative', flexShrink: 0 }}>
            <img src={group.peer_avatar} alt={group.name} className="group-icon-sm" style={{ objectFit: 'cover', padding: 0 }} />
            {isOnline && <span className="online-dot" style={{ position: 'absolute', bottom: 1, right: 1 }} />}
          </div>
        ) : group.is_managed ? (
          <div className="group-icon-sm" style={{ background: avatarColors.dm, borderRadius: 8, flexShrink: 0, fontSize: 11, fontWeight: 700 }}>
            {group.is_multi_group ? 'MG' : 'UG'}
          </div>
        ) : (
          <div className="group-icon-sm" style={{ background: group.type === 'public' ? avatarColors.public : avatarColors.dm, flexShrink: 0 }}>
            {group.type === 'public' ? '#' : isDirect ? (group.peer_real_name || group.name)[0]?.toUpperCase() : group.name[0]?.toUpperCase()}
          </div>
        )}

        <div className="flex-1 overflow-hidden">
          <div className="chat-header-name truncate">
            {isDirect ? peerName : group.name}
            {group.is_readonly ? <span className="readonly-badge" style={{ marginLeft: 8 }}>read-only</span> : null}
          </div>
          {isDirect && <div className="chat-header-sub">Private message</div>}
          {!isDirect && group.type === 'private' && <div className="chat-header-sub">Private group</div>}
        </div>

        <button
          className="btn-icon"
          onClick={() => setShowInfo(true)}
          title="Conversation info"
        >
          {iconGroupInfo ? (
            <img src={iconGroupInfo} alt="info" style={{ width: 22, height: 22, objectFit: 'contain' }} />
          ) : (
            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" width="22" height="22">
              <path strokeLinecap="round" strokeLinejoin="round" d="M15 9h3.75M15 12h3.75M15 15h3.75M4.5 19.5h15a2.25 2.25 0 0 0 2.25-2.25V6.75A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25v10.5A2.25 2.25 0 0 0 4.5 19.5Zm6-10.125a1.875 1.875 0 1 1-3.75 0 1.875 1.875 0 0 1 3.75 0Zm1.294 6.336a6.721 6.721 0 0 1-3.17.789 6.721 6.721 0 0 1-3.168-.789 3.376 3.376 0 0 1 6.338 0Z" />
            </svg>
          )}
        </button>
      </div>

      {/* Messages */}
      <div className="messages-container" ref={messagesContainerRef}>
        {hasMore && (
          <button className="load-more-btn" onClick={handleLoadMore} disabled={loading}>
            {loading ? 'Loading…' : 'Load older messages'}
          </button>
        )}

        {messages.map((msg, i) => (
          <Message
            key={msg.id}
            message={msg}
            prevMessage={messages[i - 1]}
            currentUser={currentUser}
            onReply={handleReply}
            onDelete={handleDelete}
            onReact={handleReact}
            onDirectMessage={handleDirectMessage}
            isDirect={isDirect}
            onlineUserIds={onlineUserIds}
          />
        ))}

        {typing.length > 0 && (
          <div className="typing-indicator">
            <span>{typing.map(t => t.name).join(', ')} {typing.length === 1 ? 'is' : 'are'} typing</span>
            <div className="dots"><span /><span /><span /></div>
          </div>
        )}

        <div ref={messagesEndRef} />
      </div>

      {/* Input */}
      {group.is_readonly && currentUser?.role !== 'admin' ? (
        <div className="readonly-bar">
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
            <rect x="3" y="11" width="18" height="11" rx="2" ry="2"/>
            <path d="M7 11V7a5 5 0 0 1 10 0v4"/>
          </svg>
          This channel is read-only
        </div>
      ) : (
        <MessageInput group={group} currentUser={currentUser} onSend={handleSend} socket={socket} replyTo={replyTo} onCancelReply={() => setReplyTo(null)} onTyping={() => {}} />
      )}
    </div>
      {showInfo && (
        <GroupInfoModal
          group={group}
          onClose={() => setShowInfo(false)}
          onUpdated={(updatedGroup) => { setShowInfo(false); onGroupUpdated && onGroupUpdated(updatedGroup); }}
          onBack={() => setShowInfo(false)}
        />
      )}
    </>
  );
}
