/**
 * Chat Component - Main messaging interface
 */

import React, { useState, useEffect, useRef } from 'react';
import { useSocket } from '../../contexts/SocketContext';
import ConversationList from './ConversationList';
import MessageList from './MessageList';
import MessageInput from './MessageInput';
import './Chat.css';

export default function Chat() {
  const { socket, connected } = useSocket();
  const [conversations, setConversations] = useState([]);
  const [activeConversation, setActiveConversation] = useState(null);
  const [messages, setMessages] = useState([]);
  const [loading, setLoading] = useState(true);
  const [typingUsers, setTypingUsers] = useState(new Set());
  const [error, setError] = useState(null);
  
  const typingTimeoutRef = useRef(null);

  // Load conversations on mount
  useEffect(() => {
    loadConversations();
  }, []);

  // Socket event listeners
  useEffect(() => {
    if (!socket || !connected) return;

    // New message
    socket.on('new_message', handleNewMessage);

    // Message edited
    socket.on('message_edited', handleMessageEdited);

    // Message deleted
    socket.on('message_deleted', handleMessageDeleted);

    // Reaction added
    socket.on('reaction_added', handleReactionAdded);

    // Reaction removed
    socket.on('reaction_removed', handleReactionRemoved);

    // Typing indicators
    socket.on('user_typing', handleTypingStart);
    socket.on('user_stopped_typing', handleTypingStop);

    // User status changed
    socket.on('user_status_changed', handleStatusChange);

    return () => {
      socket.off('new_message', handleNewMessage);
      socket.off('message_edited', handleMessageEdited);
      socket.off('message_deleted', handleMessageDeleted);
      socket.off('reaction_added', handleReactionAdded);
      socket.off('reaction_removed', handleReactionRemoved);
      socket.off('user_typing', handleTypingStart);
      socket.off('user_stopped_typing', handleTypingStop);
      socket.off('user_status_changed', handleStatusChange);
    };
  }, [socket, connected, activeConversation]);

  // Load conversations from API
  const loadConversations = async () => {
    try {
      const response = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:3000'}/api/messaging/conversations`, {
        headers: {
          'Authorization': `Bearer ${localStorage.getItem('token')}`
        }
      });

      const data = await response.json();

      if (data.success) {
        setConversations(data.conversations);
      } else {
        setError(data.error);
      }
    } catch (error) {
      console.error('Failed to load conversations:', error);
      setError('Failed to load conversations');
    } finally {
      setLoading(false);
    }
  };

  // Load messages for a conversation
  const loadMessages = async (conversationId) => {
    try {
      const response = await fetch(
        `${import.meta.env.VITE_API_URL || 'http://localhost:3000'}/api/messaging/conversations/${conversationId}/messages`,
        {
          headers: {
            'Authorization': `Bearer ${localStorage.getItem('token')}`
          }
        }
      );

      const data = await response.json();

      if (data.success) {
        setMessages(data.messages);

        // Mark as read
        if (data.messages.length > 0) {
          markAsRead(conversationId);
        }
      }
    } catch (error) {
      console.error('Failed to load messages:', error);
    }
  };

  // Select conversation
  const selectConversation = async (conversation) => {
    setActiveConversation(conversation);
    await loadMessages(conversation.id);
  };

  // Handle new message
  const handleNewMessage = (message) => {
    // If this conversation is active, add message
    if (activeConversation && activeConversation.id === message.conversationId) {
      setMessages(prev => [...prev, message]);

      // Mark as read
      markAsRead(message.conversationId);
    }

    // Update conversation list (move to top, update last message)
    setConversations(prev => {
      const updated = prev.map(conv => {
        if (conv.id === message.conversationId) {
          return {
            ...conv,
            lastMessage: message,
            updatedAt: message.createdAt,
            unreadCount: activeConversation?.id === message.conversationId ? 0 : conv.unreadCount + 1
          };
        }
        return conv;
      });

      // Sort by updated_at
      return updated.sort((a, b) => 
        new Date(b.updatedAt) - new Date(a.updatedAt)
      );
    });
  };

  // Handle message edited
  const handleMessageEdited = (data) => {
    const { messageId, content, editedAt } = data;

    setMessages(prev => prev.map(msg =>
      msg.id === messageId
        ? { ...msg, content: content, editedAt: editedAt }
        : msg
    ));
  };

  // Handle message deleted
  const handleMessageDeleted = (data) => {
    const { messageId } = data;
    setMessages(prev => prev.filter(msg => msg.id !== messageId));
  };

  // Handle reaction added
  const handleReactionAdded = (data) => {
    const { messageId, emoji, userId } = data;

    setMessages(prev => prev.map(msg => {
      if (msg.id === messageId) {
        const reactions = [...(msg.reactions || [])];
        const existing = reactions.find(r => r.emoji === emoji);

        if (existing) {
          if (!existing.users.includes(userId)) {
            existing.users.push(userId);
          }
        } else {
          reactions.push({
            emoji: emoji,
            users: [userId]
          });
        }

        return { ...msg, reactions: reactions };
      }
      return msg;
    }));
  };

  // Handle reaction removed
  const handleReactionRemoved = (data) => {
    const { messageId, emoji, userId } = data;

    setMessages(prev => prev.map(msg => {
      if (msg.id === messageId) {
        const reactions = (msg.reactions || [])
          .map(r => {
            if (r.emoji === emoji) {
              return {
                ...r,
                users: r.users.filter(u => u !== userId)
              };
            }
            return r;
          })
          .filter(r => r.users.length > 0);

        return { ...msg, reactions: reactions };
      }
      return msg;
    }));
  };

  // Handle typing start
  const handleTypingStart = (data) => {
    const { conversationId, userId } = data;

    if (activeConversation && activeConversation.id === conversationId) {
      setTypingUsers(prev => new Set([...prev, userId]));
    }
  };

  // Handle typing stop
  const handleTypingStop = (data) => {
    const { conversationId, userId } = data;

    if (activeConversation && activeConversation.id === conversationId) {
      setTypingUsers(prev => {
        const updated = new Set(prev);
        updated.delete(userId);
        return updated;
      });
    }
  };

  // Handle user status change
  const handleStatusChange = (data) => {
    const { userId, status } = data;

    // Update conversation participants
    setConversations(prev => prev.map(conv => ({
      ...conv,
      participants: conv.participants?.map(p =>
        p.id === userId ? { ...p, status: status } : p
      )
    })));

    // Update active conversation
    if (activeConversation) {
      setActiveConversation(prev => ({
        ...prev,
        participants: prev.participants?.map(p =>
          p.id === userId ? { ...p, status: status } : p
        )
      }));
    }
  };

  // Send message
  const sendMessage = async (content) => {
    if (!activeConversation || !content.trim()) return;

    try {
      const response = await fetch(
        `${import.meta.env.VITE_API_URL || 'http://localhost:3000'}/api/messaging/conversations/${activeConversation.id}/messages`,
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${localStorage.getItem('token')}`
          },
          body: JSON.stringify({
            content: content,
            contentType: 'text'
          })
        }
      );

      const data = await response.json();

      if (!data.success) {
        throw new Error(data.error);
      }

      // Message will be received via socket event
    } catch (error) {
      console.error('Failed to send message:', error);
      setError('Failed to send message');
    }
  };

  // Start typing indicator
  const startTyping = () => {
    if (!activeConversation || !socket) return;

    socket.emit('typing_start', {
      conversationId: activeConversation.id
    });

    // Auto-stop after 3 seconds
    if (typingTimeoutRef.current) {
      clearTimeout(typingTimeoutRef.current);
    }

    typingTimeoutRef.current = setTimeout(() => {
      stopTyping();
    }, 3000);
  };

  // Stop typing indicator
  const stopTyping = () => {
    if (!activeConversation || !socket) return;

    socket.emit('typing_stop', {
      conversationId: activeConversation.id
    });

    if (typingTimeoutRef.current) {
      clearTimeout(typingTimeoutRef.current);
      typingTimeoutRef.current = null;
    }
  };

  // Mark conversation as read
  const markAsRead = async (conversationId) => {
    try {
      await fetch(
        `${import.meta.env.VITE_API_URL || 'http://localhost:3000'}/api/messaging/conversations/${conversationId}/read`,
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${localStorage.getItem('token')}`
          }
        }
      );

      // Update local state
      setConversations(prev => prev.map(conv =>
        conv.id === conversationId ? { ...conv, unreadCount: 0 } : conv
      ));
    } catch (error) {
      console.error('Failed to mark as read:', error);
    }
  };

  if (loading) {
    return (
      <div className="chat-loading">
        <div className="spinner"></div>
        <p>Loading conversations...</p>
      </div>
    );
  }

  if (error && conversations.length === 0) {
    return (
      <div className="chat-error">
        <p>⚠️ {error}</p>
        <button onClick={loadConversations}>Retry</button>
      </div>
    );
  }

  return (
    <div className="chat-container">
      <div className="chat-status">
        {connected ? (
          <span className="status-indicator online">● Connected</span>
        ) : (
          <span className="status-indicator offline">○ Disconnected</span>
        )}
      </div>

      <ConversationList
        conversations={conversations}
        activeConversation={activeConversation}
        onSelectConversation={selectConversation}
      />

      <div className="chat-main">
        {activeConversation ? (
          <>
            <div className="chat-header">
              <div className="conversation-info">
                <div className="conversation-avatar">
                  {activeConversation.title?.[0] || '?'}
                </div>
                <div>
                  <h3>{activeConversation.title || 'Direct Message'}</h3>
                  <p className="participant-info">
                    {activeConversation.otherParticipants?.length || 0} participants
                  </p>
                </div>
              </div>
            </div>

            <MessageList
              messages={messages}
              typingUsers={Array.from(typingUsers)}
            />

            <MessageInput
              onSend={sendMessage}
              onTyping={startTyping}
              onStopTyping={stopTyping}
            />
          </>
        ) : (
          <div className="no-conversation-selected">
            <p>Select a conversation to start messaging</p>
            <p className="hint">or create a new conversation</p>
          </div>
        )}
      </div>
    </div>
  );
}
