import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
import { messagingService, socket, connectSocket, disconnectSocket } from '../services/messaging';
import { useAuth } from './AuthContext';

const MessagingContext = createContext();

export function useMessaging() {
  const context = useContext(MessagingContext);
  if (!context) {
    throw new Error('useMessaging must be used within a MessagingProvider');
  }
  return context;
}

export function MessagingProvider({ children }) {
  const { user } = useAuth();
  const [conversations, setConversations] = useState([]);
  const [currentConversation, setCurrentConversation] = useState(null);
  const [messages, setMessages] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  // Load conversations when user logs in
  useEffect(() => {
    if (user?.id) {
      connectSocket(user.id);
      loadConversations();
    } else {
      disconnectSocket();
      setConversations([]);
      setMessages([]);
    }

    return () => {
      disconnectSocket();
    };
  }, [user?.id]);

  // Listen for real-time messages
  useEffect(() => {
    const handleNewMessage = (message) => {
      if (message.conversation_id === currentConversation?.id) {
        setMessages(prev => [...prev, message]);
      }
      // Update conversation's last message
      setConversations(prev =>
        prev.map(conv =>
          conv.id === message.conversation_id
            ? { ...conv, lastMessage: message, updated_at: message.created_at }
            : conv
        )
      );
    };

    socket.on('message:new', handleNewMessage);
    return () => {
      socket.off('message:new', handleNewMessage);
    };
  }, [currentConversation?.id]);

  // Subscribe to current conversation's messages
  useEffect(() => {
    if (!currentConversation?.id) return;

    const unsubscribe = messagingService.subscribeToMessages(
      currentConversation.id,
      (newMessage) => {
        setMessages(prev => {
          // Avoid duplicates
          if (prev.find(m => m.id === newMessage.id)) return prev;
          return [...prev, newMessage];
        });
      }
    );

    return unsubscribe;
  }, [currentConversation?.id]);

  const loadConversations = useCallback(async () => {
    if (!user?.id) return;
    
    setLoading(true);
    try {
      const data = await messagingService.getConversations(user.id);
      setConversations(data);
    } catch (err) {
      console.error('Failed to load conversations:', err);
      setError(err.message);
    } finally {
      setLoading(false);
    }
  }, [user?.id]);

  const selectConversation = useCallback(async (conversation) => {
    setCurrentConversation(conversation);
    setLoading(true);
    try {
      const msgs = await messagingService.getMessages(conversation.id);
      setMessages(msgs);
    } catch (err) {
      console.error('Failed to load messages:', err);
      setError(err.message);
    } finally {
      setLoading(false);
    }
  }, []);

  const sendMessage = useCallback(async (content) => {
    if (!currentConversation?.id || !user?.id || !content.trim()) return;

    try {
      const message = await messagingService.sendMessage(
        currentConversation.id,
        user.id,
        content
      );
      // Optimistically add to local state
      setMessages(prev => [...prev, message]);
    } catch (err) {
      console.error('Failed to send message:', err);
      setError(err.message);
    }
  }, [currentConversation?.id, user?.id]);

  const createConversation = useCallback(async (type, title, participantIds) => {
    if (!user?.id) return;

    try {
      const conversation = await messagingService.createConversation(
        type,
        title,
        [user.id, ...participantIds]
      );
      setConversations(prev => [conversation, ...prev]);
      return conversation;
    } catch (err) {
      console.error('Failed to create conversation:', err);
      setError(err.message);
    }
  }, [user?.id]);

  const value = {
    conversations,
    currentConversation,
    messages,
    loading,
    error,
    selectConversation,
    sendMessage,
    createConversation,
    refreshConversations: loadConversations,
  };

  return (
    <MessagingContext.Provider value={value}>
      {children}
    </MessagingContext.Provider>
  );
}
