'use client';

import { useState, useEffect, useRef } from 'react';
import { useSession } from 'next-auth/react';
import MessageInput from './MessageInput';
import BidActionHeader from './BidActionHeader';
import { useWebSocketContext } from '@/context/WebSocketContext';

interface Profile {
  firstName?: string;
  lastName?: string;
  profileImage?: string;
}

interface User {
  id: string;
  email: string;
  profile?: Profile;
}

interface Message {
  id: string;
  content: string;
  attachments?: string;
  senderId: string;
  receiverId: string;
  sender: User;
  receiver: User;
  isRead: boolean;
  readAt?: string;
  createdAt: string;
  project?: {
    id: string;
    title: string;
  };
  isOptimistic?: boolean; // Flag for optimistic messages
}

interface MessageThreadProps {
  contact: User;
  projectId?: string;
  projectStatus?: string;
}

export default function MessageThread({ contact, projectId, projectStatus }: MessageThreadProps) {
  // Check if project is archived (completed or cancelled)
  const isProjectArchived = projectStatus === 'completed' || projectStatus === 'cancelled';
  console.log('🔍 [MessageThread] Project status:', projectStatus);
  const { data: session } = useSession();
  const [messages, setMessages] = useState<Message[]>([]);
  const [loading, setLoading] = useState(false);
  const [page, setPage] = useState(1);
  const [hasMore, setHasMore] = useState(false);
  const [isTyping, setIsTyping] = useState(false);
  const messagesEndRef = useRef<HTMLDivElement>(null);
  const messagesContainerRef = useRef<HTMLDivElement>(null);
  const typingTimeoutRef = useRef<NodeJS.Timeout | null>(null);

  const { isConnected, sendMessage: sendWebSocketMessage, joinRoom, leaveRoom, lastMessage } = useWebSocketContext();

  useEffect(() => {
    if (lastMessage) {
      console.log('🎯 [MessageThread] WebSocket message received in useEffect:', lastMessage);
      try {
        const message = typeof lastMessage === 'string' ? JSON.parse(lastMessage) : lastMessage;
        console.log('🔍 [MessageThread] Parsed message:', message);
        
        switch (message.type) {
          case 'new_message':
            console.log('📨 [MessageThread] Handling new_message case');
            handleNewMessage(message);
            break;
            
          case 'typing_start':
            handleTypingStart(message);
            break;
            
          case 'typing_stop':
            handleTypingStop(message);
            break;
            
          case 'message_read':
            handleMessageRead(message);
            break;
            
          case 'user_online':
          case 'user_offline':
            // Could update user presence indicator
            break;
            
          case 'message_sent':
            // Message sent confirmation
            break;
            
          case 'error':
            console.warn('WebSocket error:', message.error);
            break;
            
          default:
            console.log('Unknown WebSocket message type:', message.type);
        }
      } catch (error) {
        console.error('❌ [MessageThread] Error processing WebSocket message:', error);
      }
    }
  }, [lastMessage]);

  // Handle new message WebSocket event
  const handleNewMessage = (message: any) => {
    console.log('🔄 [MessageThread] Handling new_message:', message);
    if (!message.message) {
      console.log('❌ [MessageThread] No message data in new_message event');
      return;
    }
    
    // Use session user email consistently (matches WebSocket authentication)
    const currentUserEmail = session?.user?.email;
    const currentUserId = (session?.user as any)?.id;
    const msgSenderId = message.message.senderId;
    const msgReceiverId = message.message.receiverId;
    
    console.log('🔍 [MessageThread] User IDs:', {
      currentUserEmail,
      currentUserId,
      msgSenderId,
      msgReceiverId,
      contactId: contact.id,
      contactEmail: contact.email
    });
    
    // Check if this message is relevant to the current conversation
    // Use ID for comparison since that's what the database uses
    const isRelevant = (
      (msgSenderId === contact.id && msgReceiverId === currentUserId) ||
      (msgSenderId === currentUserId && msgReceiverId === contact.id)
    );
    
    console.log('🔍 [MessageThread] Message relevance check:', {
      isRelevant,
      isFromContact: msgSenderId === contact.id,
      isToCurrentUser: msgReceiverId === currentUserId,
      isFromCurrentUser: msgSenderId === currentUserId,
      isToContact: msgReceiverId === contact.id
    });
    
    // Process all relevant messages (including our own for real-time updates)
    if (isRelevant) {
      console.log('✅ [MessageThread] Adding new message to conversation');
      setMessages(prev => {
        // Check for existing message by ID
        const existsById = prev.some(m => m.id === message.message.id);
        
        // For messages from current user, check if we have an optimistic version
        if (msgSenderId === currentUserId) {
          const hasOptimistic = prev.some(m => m.isOptimistic && 
            m.senderId === msgSenderId && 
            m.receiverId === msgReceiverId &&
            Math.abs(new Date(m.createdAt).getTime() - new Date(message.message.createdAt).getTime()) < 5000
          );
          
          if (hasOptimistic && !existsById) {
            // Replace optimistic message with real one
            console.log('🔄 [MessageThread] Replacing optimistic message with real WebSocket message');
            return prev.map(m => 
              m.isOptimistic && 
              m.senderId === msgSenderId && 
              m.receiverId === msgReceiverId &&
              Math.abs(new Date(m.createdAt).getTime() - new Date(message.message.createdAt).getTime()) < 5000
                ? { ...message.message, isOptimistic: false }
                : m
            );
          } else if (existsById) {
            // Real message already exists, skip
            console.log('⚠️ [MessageThread] Real message already exists, skipping');
            return prev;
          }
        }
        
        // For new messages (not duplicates)
        if (!existsById) {
          const newMessages = [...prev, message.message];
          
          // Auto-scroll to bottom for new messages
          setTimeout(() => scrollToBottom(true), 100);
          
          // Mark message as read if tab is active and message is from other user
          if (!document.hidden && msgSenderId !== currentUserId) {
            setTimeout(() => markMessageAsRead(message.message.id), 500);
          }
          
          return newMessages;
        }
        
        console.log('⚠️ [MessageThread] Message already exists, skipping');
        return prev;
      });
      
      // Show browser notification for new messages when tab is not active (only for messages from others)
      if (document.hidden && msgSenderId !== currentUserId) {
        showNotification(message.message);
      }
    } else {
      console.log('❌ [MessageThread] Message not relevant or from current user, ignoring');
    }
  };

  // Handle typing start WebSocket event
  const handleTypingStart = (message: any) => {
    if (message.userId === contact.id || message.userId === contact.email) {
      setIsTyping(true);
      // Clear any existing timeout
      if (typingTimeoutRef.current) {
        clearTimeout(typingTimeoutRef.current);
      }
      // Auto-stop typing after 5 seconds if no typing_stop received
      typingTimeoutRef.current = setTimeout(() => {
        setIsTyping(false);
      }, 5000);
    }
  };

  // Handle typing stop WebSocket event
  const handleTypingStop = (message: any) => {
    if (message.userId === contact.id || message.userId === contact.email) {
      setIsTyping(false);
      if (typingTimeoutRef.current) {
        clearTimeout(typingTimeoutRef.current);
        typingTimeoutRef.current = null;
      }
    }
  };

  // Handle message read WebSocket event
  const handleMessageRead = (message: any) => {
    if (message.messageIds && Array.isArray(message.messageIds)) {
      setMessages(prev => prev.map(msg => 
        message.messageIds.includes(msg.id) 
          ? { ...msg, isRead: true, readAt: message.readAt || new Date().toISOString() }
          : msg
      ));
    }
  };

  useEffect(() => {
    console.log('🔄 [MessageThread] Main effect triggered:', {
      hasSession: !!session?.user?.email,
      contactId: contact.id,
      isConnected,
      sessionUserId: (session?.user as any)?.id
    });
    
    if (session?.user?.email && contact.id) {
      console.log('💼 [MessageThread] Initializing conversation with:', contact.id);
      setMessages([]);
      setPage(1);
      fetchMessages(1, true);
      markConversationAsRead();
      
      // Join conversation room for real-time updates using consistent room naming
      if (isConnected && session?.user) {
        const currentUserId = (session.user as any)?.id;
        // Create a consistent room ID regardless of who initiates the conversation
        const roomId = `conversation_${currentUserId < contact.id ? currentUserId : contact.id}_${currentUserId < contact.id ? contact.id : currentUserId}`;
        console.log(`🚪 [MessageThread] Joining room: ${roomId} (isConnected: ${isConnected})`);
        joinRoom(roomId);
      } else {
        console.log('⚠️ [MessageThread] Not connected to WebSocket yet, cannot join room');
      }
    }
    
    return () => {
      // Leave conversation room on cleanup
      if (isConnected && contact.id && session?.user) {
        const currentUserId = (session.user as any)?.id;
        const roomId = `conversation_${currentUserId < contact.id ? currentUserId : contact.id}_${currentUserId < contact.id ? contact.id : currentUserId}`;
        console.log(`🚪 [MessageThread] Leaving room: ${roomId}`);
        leaveRoom(roomId);
      }
    };
  }, [session, contact.id, projectId, isConnected, joinRoom, leaveRoom]);

  useEffect(() => {
    // Use setTimeout to ensure DOM is updated before scrolling
    const timer = setTimeout(() => {
      scrollToBottom();
    }, 100);
    
    return () => clearTimeout(timer);
  }, [messages]);

  // Additional effect to scroll when component first loads
  useEffect(() => {
    if (messages.length > 0) {
      const timer = setTimeout(() => {
        scrollToBottom();
      }, 200);
      
      return () => clearTimeout(timer);
    }
  }, [messages.length > 0]);

  // Initialize notification permissions
  useEffect(() => {
    requestNotificationPermission();
  }, []);

  const fetchMessages = async (pageNum: number = page, reset: boolean = false) => {
    try {
      setLoading(true);
      const params = new URLSearchParams({
        contactId: contact.id,
        page: pageNum.toString(),
        limit: '50'
      });
      
      if (projectId) {
        params.append('projectId', projectId);
      }

      const response = await fetch(`/api/messages/conversations/${contact.id}?${params}`);
      if (response.ok) {
        const data = await response.json();
        if (reset) {
          setMessages(data.data.messages);
        } else {
          setMessages(prev => [...data.data.messages, ...prev]);
        }
        setHasMore(data.data.pagination.hasNext);
      }
    } catch (error) {
    } finally {
      setLoading(false);
    }
  };


  const markConversationAsRead = async () => {
    try {
      await fetch(`/api/messages/conversations/${contact.id}`, {
        method: 'PUT'
      });
    } catch (error) {
    }
  };

  const markMessageAsRead = async (messageId: string) => {
    try {
      await fetch(`/api/messages/${messageId}`, {
        method: 'PUT',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ isRead: true }),
      });

      // Send WebSocket notification about read status
      if (isConnected) {
        sendWebSocketMessage({
          type: 'message_read',
          messageId,
          receiverId: contact.email || contact.id,
        });
      }
    } catch (error) {
    }
  };

  const showNotification = (message: Message) => {
    if ('Notification' in window && Notification.permission === 'granted') {
      const senderName = getDisplayName(message.sender);
      new Notification(`New message from ${senderName}`, {
        body: message.content.slice(0, 100) + (message.content.length > 100 ? '...' : ''),
        icon: getProfileImage(message.sender),
        tag: `message-${message.id}`,
      });
    }
  };

  const requestNotificationPermission = () => {
    if ('Notification' in window && Notification.permission === 'default') {
      Notification.requestPermission();
    }
  };

  const sendMessage = async (content: string, attachments?: any[]) => {
    const currentUserId = (session?.user as any)?.id;
    
    // Create optimistic message for immediate UI feedback
    const optimisticMessage: Message = {
      id: `temp_${Date.now()}`,
      content: content.trim(),
      attachments: attachments ? JSON.stringify(attachments) : undefined,
      senderId: currentUserId,
      receiverId: contact.id,
      sender: {
        id: currentUserId,
        email: session?.user?.email || '',
        profile: {
          firstName: session?.user?.name?.split(' ')[0] || '',
          lastName: session?.user?.name?.split(' ')[1] || '',
          profileImage: session?.user?.image || '/assets/image/harveyspecter.png'
        }
      },
      receiver: contact,
      isRead: false,
      readAt: undefined,
      createdAt: new Date().toISOString(),
      project: projectId ? { id: projectId, title: 'Project' } : undefined,
      isOptimistic: true // Flag to identify optimistic messages
    };

    try {
      // Add optimistic message immediately for better UX
      setMessages(prev => [...prev, optimisticMessage]);
      
      // Scroll to bottom immediately
      setTimeout(() => scrollToBottom(), 50);

      // Send via HTTP API for persistence
      const response = await fetch('/api/messages', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          receiverId: contact.id,
          content,
          attachments,
          projectId
        }),
      });

      if (response.ok) {
        const data = await response.json();
        // We no longer replace the optimistic message here.
        // The replacement is now handled by the WebSocket 'new_message' event.
        console.log('✅ [MessageThread] Message sent via API, waiting for WebSocket confirmation.');
      } else {
        // Remove optimistic message on failure
        setMessages(prev => prev.filter(msg => msg.id !== optimisticMessage.id));
        
        const errorData = await response.json();
        throw new Error(`Failed to send message: ${errorData.error || 'Unknown error'}`);
      }
    } catch (error) {
      // Remove optimistic message on error
      setMessages(prev => prev.filter(msg => msg.id !== optimisticMessage.id));
      throw error;
    }
  };

  const handleTyping = (isTyping: boolean) => {
    if (isConnected) {
      sendWebSocketMessage({
        type: isTyping ? 'typing_start' : 'typing_stop',
        receiverId: contact.email || contact.id
      });
    }
  };

  const scrollToBottom = (smooth: boolean = false) => {
    if (messagesContainerRef.current) {
      requestAnimationFrame(() => {
        if (messagesContainerRef.current) {
          const container = messagesContainerRef.current;
          if (smooth) {
            container.scrollTo({
              top: container.scrollHeight,
              behavior: 'smooth'
            });
          } else {
            container.scrollTop = container.scrollHeight;
          }
        }
      });
    }
  };

  const loadMoreMessages = () => {
    if (!loading && hasMore) {
      const nextPage = page + 1;
      setPage(nextPage);
      fetchMessages(nextPage);
    }
  };

  const formatTime = (dateString: string) => {
    const date = new Date(dateString);
    return date.toLocaleTimeString('en-US', { 
      hour: '2-digit', 
      minute: '2-digit',
      hour12: true
    });
  };

  const formatDate = (dateString: string) => {
    const date = new Date(dateString);
    const today = new Date();
    const yesterday = new Date(today);
    yesterday.setDate(yesterday.getDate() - 1);

    if (date.toDateString() === today.toDateString()) {
      return 'Today';
    } else if (date.toDateString() === yesterday.toDateString()) {
      return 'Yesterday';
    } else {
      return date.toLocaleDateString('en-US', { 
        month: 'short', 
        day: 'numeric',
        year: date.getFullYear() !== today.getFullYear() ? 'numeric' : undefined
      });
    }
  };

  const getDisplayName = (user: User) => {
    if (user.profile?.firstName && user.profile?.lastName) {
      return `${user.profile.firstName} ${user.profile.lastName}`;
    }
    return user.email;
  };

  const getProfileImage = (user: User) => {
    return user.profile?.profileImage || '/assets/image/harveyspecter.png';
  };

  const renderMessage = (message: Message, index: number) => {
    const isOwnMessage = message.senderId === (session?.user as any)?.id;
    const isOptimistic = message.isOptimistic;

    return (
      <li key={message.id} className={`${isOwnMessage ? 'replies' : 'sent'} ${isOptimistic ? 'optimistic' : ''}`}>
        <img 
          src={getProfileImage(message.sender)} 
          alt={getDisplayName(message.sender)} 
        />
        <div>
          <p style={isOptimistic ? { opacity: 0.7, fontStyle: 'italic' } : {}}>
            {message.content}
          </p>
          <div className="message-meta-info">
            <span className="message-time">{formatTime(message.createdAt)}</span>
            {isOwnMessage && (
              <span className={`read-receipt ${message.isRead ? 'read' : 'sent'}`}>
                {isOptimistic ? '⏳' : (message.isRead ? '✓✓' : '✓')}
              </span>
            )}
          </div>
          {message.attachments && (
            <div className="attachments-list">
              {JSON.parse(message.attachments).map((attachment: any, idx: number) => (
                <div key={idx} className="attachment-item">
                  <a 
                    href={attachment.url} 
                    target="_blank" 
                    rel="noopener noreferrer"
                  >
                    📎 {attachment.name}
                  </a>
                </div>
              ))}
            </div>
          )}
        </div>
      </li>
    );
  };

  if (!session?.user) {
    return null;
  }

  return (
    <div className="content">
      <div className="contact-profile">
        <img src={getProfileImage(contact)} alt={getDisplayName(contact)} />
        <div className="user-name-chat">
          <p>{getDisplayName(contact)}</p>
          
        </div>
      </div>
      
      {/* Show bid action header for clients when there's a project context */}
      {projectId && (
        <BidActionHeader 
          contactId={contact.id}
          projectId={projectId}
          onBidAction={(bidId, action) => {
            // Refresh messages after bid action to show system messages
            fetchMessages(1, true);
          }}
        />
      )}
      
      <div className="messages" ref={messagesContainerRef}>
        <ul>
          {hasMore && (
            <li style={{ textAlign: 'center', margin: '20px 0' }}>
              <button
                onClick={loadMoreMessages}
                disabled={loading}
                style={{ 
                  padding: '8px 16px', 
                  border: '1px solid #ddd', 
                  borderRadius: '4px',
                  background: 'white',
                  cursor: loading ? 'not-allowed' : 'pointer'
                }}
              >
                {loading ? 'Loading...' : 'Load older messages'}
              </button>
            </li>
          )}

          {loading && messages.length === 0 ? (
            <li style={{ textAlign: 'center', padding: '40px' }}>
              <div>Loading...</div>
            </li>
          ) : messages.length === 0 ? (
            <li style={{ textAlign: 'center', padding: '40px' }}>
              <img src="/assets/image/message-chat.svg" alt="" width="64" height="64" style={{ opacity: '0.5', marginBottom: '12px' }} />
              <p>No messages yet. Start the conversation!</p>
            </li>
          ) : (
            messages.map((message, index) => renderMessage(message, index))
          )}

          {/* Typing Indicator */}
          {isTyping && (
            <li className="typing-indicator" style={{ textAlign: 'left', padding: '10px 20px' }}>
              <div className="typing-dots" style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
                <span style={{ fontSize: '14px', color: '#666' }}>
                  {getDisplayName(contact)} is typing
                </span>
                <div style={{ display: 'flex', gap: '2px' }}>
                  <div className="typing-dot" style={{ 
                    width: '6px', 
                    height: '6px', 
                    backgroundColor: '#007bff',
                    borderRadius: '50%',
                    animation: 'typingBounce 1.4s infinite ease-in-out both',
                    animationDelay: '0s'
                  }}></div>
                  <div className="typing-dot" style={{ 
                    width: '6px', 
                    height: '6px', 
                    backgroundColor: '#007bff',
                    borderRadius: '50%',
                    animation: 'typingBounce 1.4s infinite ease-in-out both',
                    animationDelay: '0.16s'
                  }}></div>
                  <div className="typing-dot" style={{ 
                    width: '6px', 
                    height: '6px', 
                    backgroundColor: '#007bff',
                    borderRadius: '50%',
                    animation: 'typingBounce 1.4s infinite ease-in-out both',
                    animationDelay: '0.32s'
                  }}></div>
                </div>
              </div>
            </li>
          )}
        </ul>

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

      {isProjectArchived ? (
        <div className="archived-project-notice">
          <div className="notice-content">
            <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
              <path d="M10 18.3333C14.6024 18.3333 18.3333 14.6024 18.3333 10C18.3333 5.39763 14.6024 1.66667 10 1.66667C5.39763 1.66667 1.66667 5.39763 1.66667 10C1.66667 14.6024 5.39763 18.3333 10 18.3333Z" stroke="#6B7280" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
              <path d="M10 6.66667V10" stroke="#6B7280" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
              <path d="M10 13.3333H10.0083" stroke="#6B7280" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
            </svg>
            <span>
              This project has been {projectStatus}. Messaging is no longer available.
              {projectStatus === 'completed' && (
                <> You can now <a href={`/review/${projectId}`} style={{ color: '#EF7310', textDecoration: 'none' }}>leave a review</a>.</>
              )}
            </span>
          </div>
        </div>
      ) : (
        <MessageInput 
          onSendMessage={sendMessage}
          onTyping={handleTyping}
          placeholder={`Message ${getDisplayName(contact)}...`}
          disabled={isProjectArchived}
        />
      )}
    </div>
  );
}