import { useState, useEffect, useRef } from 'react';
import { apiFetch } from '@/utils/api';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Loader2, Hash, MessageSquare, ChevronUp, Search, ExternalLink, FileText, Image, Download, MessageCircle, Users2 } from 'lucide-react';
import { Input } from '@/components/ui/input';
import config from '@/config';
import { convertEmojiShortcodes } from '@/utils/emojiUtils';

interface Message {
  id: number;
  msg: string;
  ts: string;
  u: {
    _id: string;
    username: string;
    name?: string;
  };
  _updatedat: string;
  urls?: any[];
  mentions?: any[];
  md?: any[];
  attachments?: {
    id: number;
    mongo_id: string;
    name: string;
    size: number;
    type: string;
    url: string;
    path: string;
    typegroup: string;
    identify?: {
      size?: { width: number; height: number };
      format?: string;
    };
  }[];
}

interface Room {
  id: number;
  name: string;
  fname: string;
  type: string;
  msgs: number;
  last_message_date: string;
  display_name: string;
  description?: string;
  teamid?: string;
  participants?: { username: string; name: string }[];
}

interface ChatRoomProps {
  roomId: string;
  selectedUserId: string;
}

export function ChatRoom({ roomId, selectedUserId }: ChatRoomProps) {
  const [room, setRoom] = useState<Room | null>(null);
  const [messages, setMessages] = useState<Message[]>([]);
  const [loading, setLoading] = useState(false);
  const [loadingMore, setLoadingMore] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [hasMore, setHasMore] = useState(true);
  const [searchQuery, setSearchQuery] = useState('');
  const [showSearch, setShowSearch] = useState(false);
  
  const messagesEndRef = useRef<HTMLDivElement>(null);
  const messagesContainerRef = useRef<HTMLDivElement>(null);

  const scrollToBottom = () => {
    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
  };

  const fetchRoom = async () => {
    try {
      const response = await apiFetch(`${config.chatUrl}/rooms/${roomId}?userId=${selectedUserId}`);
      const data = await response.json();
      
      if (data.status === 'success') {
        setRoom(data.room);
      } else {
        throw new Error(data.error || 'Failed to fetch room');
      }
    } catch (err) {
      console.error('Error fetching room:', err);
      setError(err instanceof Error ? err.message : 'An error occurred');
    }
  };

  const fetchMessages = async (before?: string, append = false) => {
    if (!append) setLoading(true);
    else setLoadingMore(true);
    
    try {
      const params = new URLSearchParams({
        limit: '50',
        offset: append ? messages.length.toString() : '0'
      });
      
      if (before) {
        params.set('before', before);
      }
      
      const response = await apiFetch(`${config.chatUrl}/rooms/${roomId}/messages?${params}`);
      const data = await response.json();
      
      if (data.status === 'success') {
        const newMessages = data.messages;
        
        if (append) {
          // Prepend older messages
          setMessages(prev => [...newMessages, ...prev]);
          setHasMore(newMessages.length === 50);
        } else {
          setMessages(newMessages);
          setHasMore(newMessages.length === 50);
          // Scroll to bottom on initial load
          setTimeout(scrollToBottom, 100);
        }
        
        // Load attachments for these messages in the background (non-blocking)
        if (newMessages.length > 0) {
          loadAttachments(newMessages.map((m: Message) => m.id));
        }
      } else {
        throw new Error(data.error || 'Failed to fetch messages');
      }
    } catch (err) {
      console.error('Error fetching messages:', err);
      setError(err instanceof Error ? err.message : 'An error occurred');
    } finally {
      setLoading(false);
      setLoadingMore(false);
    }
  };

  const loadAttachments = async (messageIds: number[]) => {
    try {
      const response = await apiFetch(`${config.chatUrl}/messages/attachments`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ messageIds }),
      });
      
      const data = await response.json();
      
      if (data.status === 'success' && data.attachments) {
        // Update messages with their attachments
        setMessages(prevMessages => 
          prevMessages.map(msg => ({
            ...msg,
            attachments: data.attachments[msg.id] || []
          }))
        );
      }
    } catch (err) {
      console.error('Error loading attachments:', err);
      // Don't show error to user for attachments - messages are already displayed
    }
  };

  const loadMoreMessages = () => {
    if (messages.length > 0 && hasMore && !loadingMore) {
      const oldestMessage = messages[0];
      fetchMessages(oldestMessage.ts, true);
    }
  };

  const searchMessages = async () => {
    if (!searchQuery || searchQuery.length < 2) return;
    
    try {
      const response = await apiFetch(
        `${config.chatUrl}/users/${selectedUserId}/search?q=${encodeURIComponent(searchQuery)}&limit=20`
      );
      const data = await response.json();
      
      if (data.status === 'success') {
        // Handle search results
      }
    } catch (err) {
      console.error('Error searching messages:', err);
    }
  };

  useEffect(() => {
    if (roomId && selectedUserId) {
      setMessages([]);
      setError(null);
      setHasMore(true);
      fetchRoom();
      fetchMessages();
    }
  }, [roomId, selectedUserId]);

  const getRoomIcon = (room: Room) => {
    switch (room.type) {
      case 'c':
        return <Hash className="h-4 w-4 text-blue-500" />;
      case 'p':
        // Distinguish between teams and discussions based on teamid
        if (room.teamid) {
          return <Users2 className="h-4 w-4 text-purple-500" />; // Teams
        } else {
          return <MessageCircle className="h-4 w-4 text-orange-500" />; // Discussions
        }
      case 'd':
        return <MessageSquare className="h-4 w-4 text-green-500" />;
      default:
        return <Hash className="h-4 w-4 text-gray-500" />;
    }
  };

  const formatTime = (timestamp: string) => {
    // The stored timestamps are actually in Eastern Time but labeled as UTC
    // We need to compensate by treating them as UTC and then converting back to Eastern
    const originalDate = new Date(timestamp);
    
    // Subtract 4 hours to compensate for the EDT offset (adjust to 5 hours for EST months)
    // This assumes the original data was incorrectly stored as UTC when it was actually EDT/EST
    const isDST = (date: Date) => {
      const jan = new Date(date.getFullYear(), 0, 1);
      const jul = new Date(date.getFullYear(), 6, 1);
      return date.getTimezoneOffset() < Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
    };
    
    // Determine if the timestamp falls in DST period for Eastern Time
    const offsetHours = isDST(originalDate) ? 4 : 5; // EDT = UTC-4, EST = UTC-5
    const correctedDate = new Date(originalDate.getTime() - (offsetHours * 60 * 60 * 1000));
    
    const now = new Date();
    const timeZone = 'America/New_York';
    
    // Compare dates in Eastern Time to ensure correct "today" detection
    const dateInET = correctedDate.toLocaleDateString([], { timeZone });
    const nowInET = now.toLocaleDateString([], { timeZone });
    const isToday = dateInET === nowInET;
    
    if (isToday) {
      return correctedDate.toLocaleTimeString([], { 
        hour: '2-digit', 
        minute: '2-digit',
        timeZone 
      });
    } else {
      return correctedDate.toLocaleDateString([], { timeZone }) + ' ' + correctedDate.toLocaleTimeString([], { 
        hour: '2-digit', 
        minute: '2-digit',
        timeZone 
      });
    }
  };

  const renderMessageText = (text: string, urls?: any[]) => {
    if (!text) return '';
    
    // First, convert emoji shortcodes to actual emoji
    let processedText = convertEmojiShortcodes(text);
    
    // Then, handle markdown links [text](url) and convert them to HTML
    processedText = processedText.replace(
      /\[([^\]]+)\]\((https?:\/\/[^\s\)]+)\)/g,
      '<a href="$2" target="_blank" rel="noopener noreferrer" class="text-blue-600 hover:underline">$1</a>'
    );
    
    // If we have URL previews, replace standalone URLs (that aren't already in markdown) with just the preview
    if (urls && urls.length > 0) {
      urls.forEach((urlData) => {
        // Only replace standalone URLs that aren't part of markdown links
        const standaloneUrlRegex = new RegExp(`(?<!\\]\\()${urlData.url.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?!\\))`, 'g');
        processedText = processedText.replace(standaloneUrlRegex, '');
      });
    }
    
    return <span dangerouslySetInnerHTML={{ __html: processedText }} />;
  };

  const renderURLPreviews = (urls: any[]) => {
    if (!urls || urls.length === 0) return null;
    
    return (
      <div className="mt-2 space-y-2">
        {urls.map((urlData, index) => (
          <div key={index} className="border rounded-lg p-3 bg-gray-50">
            <div className="flex items-start gap-2">
              <ExternalLink className="h-4 w-4 mt-1 text-blue-500 flex-shrink-0" />
              <div className="min-w-0 flex-1">
                <a 
                  href={urlData.url} 
                  target="_blank" 
                  rel="noopener noreferrer"
                  className="text-blue-600 hover:underline text-sm break-all"
                >
                  {urlData.meta?.pageTitle || urlData.url}
                </a>
                {urlData.meta?.ogDescription && (
                  <div className="text-xs text-muted-foreground mt-1">{urlData.meta.ogDescription}</div>
                )}
              </div>
            </div>
          </div>
        ))}
      </div>
    );
  };

    const renderAttachments = (attachments: any[]) => {
    if (!attachments || attachments.length === 0) return null;
    
    // Filter out thumbnail attachments (they're usually lower quality versions)
    const filteredAttachments = attachments.filter(attachment => 
      !attachment.name?.toLowerCase().startsWith('thumb-')
    );
    
    if (filteredAttachments.length === 0) return null;
    
    return (
      <div className="mt-2 space-y-2">
        {filteredAttachments.map((attachment, index) => {
          const isImage = attachment.typegroup === 'image';
          const filePath = `${config.chatUrl}/files/by-id/${attachment.mongo_id}`;
          
          const handleDownload = () => {
            // Create a temporary anchor element to trigger download
            const link = document.createElement('a');
            link.href = filePath;
            link.download = attachment.name || 'download';
            link.target = '_blank';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
          };
          
          return (
            <div key={index} className="border rounded-lg p-3 bg-gray-50">
              <div className="flex items-center gap-2">
                {isImage ? (
                  <Image className="h-4 w-4 text-green-500" />
                ) : (
                  <FileText className="h-4 w-4 text-blue-500" />
                )}
                <div className="flex-1 min-w-0">
                  <div className="font-medium text-sm truncate">{attachment.name}</div>
                  <div className="text-xs text-muted-foreground">
                    {(attachment.size / 1024).toFixed(1)} KB
                    {attachment.identify?.size && (
                      <span> • {attachment.identify.size.width}×{attachment.identify.size.height}</span>
                    )}
                  </div>
                </div>
                <Button variant="ghost" size="sm" onClick={handleDownload}>
                  <Download className="h-4 w-4" />
                </Button>
              </div>
              {isImage && attachment.identify?.size && (
                <div className="mt-2">
                  <img 
                    src={filePath}
                    alt={attachment.name}
                    className="max-w-xs max-h-48 rounded border cursor-pointer"
                    loading="lazy"
                    onClick={() => window.open(filePath, '_blank')}
                  />
                </div>
              )}
            </div>
          );
        })}
      </div>
    );
  };

  const renderMentions = (text: string, mentions: any[]) => {
    if (!mentions || mentions.length === 0) return text;
    
    // First, convert emoji shortcodes to actual emoji
    let renderedText = convertEmojiShortcodes(text);
    
    // Then process mentions
    mentions.forEach((mention) => {
      if (mention.username) {
        const mentionPattern = new RegExp(`@${mention.username}`, 'g');
        renderedText = renderedText.replace(
          mentionPattern, 
          `<span class="bg-blue-100 text-blue-800 px-1 rounded">@${mention.username}</span>`
        );
      }
    });
    
    return <span dangerouslySetInnerHTML={{ __html: renderedText }} />;
  };

  const renderMessage = (message: Message, index: number) => {
    const prevMessage = index > 0 ? messages[index - 1] : null;
    const isConsecutive = prevMessage && 
      prevMessage.u.username === message.u.username &&
      new Date(message.ts).getTime() - new Date(prevMessage.ts).getTime() < 300000; // 5 minutes

    return (
      <div key={message.id} className={`${isConsecutive ? 'mt-1' : 'mt-4'}`}>
        {!isConsecutive && (
          <div className="flex items-center gap-2 mb-1">
            <Avatar className="h-8 w-8">
              <AvatarImage 
                src={`${config.chatUrl}/avatar/${message.u._id}`}
                alt={message.u.name || message.u.username}
              />
              <AvatarFallback className="text-sm font-medium">
                {(message.u.name || message.u.username).charAt(0).toUpperCase()}
              </AvatarFallback>
            </Avatar>
            <span className="font-medium text-sm">
              {message.u.name || message.u.username}
            </span>
            <span className="text-xs text-muted-foreground">
              {formatTime(message.ts)}
            </span>
          </div>
        )}
        <div className={`${isConsecutive ? 'ml-10' : 'ml-10'} text-sm`}>
          <div className="break-words">
            {message.mentions && message.mentions.length > 0 
              ? renderMentions(message.msg, message.mentions)
              : renderMessageText(message.msg, message.urls)
            }
          </div>
          {message.urls && renderURLPreviews(message.urls)}
          {message.attachments && renderAttachments(message.attachments)}
        </div>
      </div>
    );
  };

  if (!roomId) {
    return (
      <Card className="h-full">
        <CardContent className="flex items-center justify-center h-full">
          <p className="text-muted-foreground">Select a room to view messages</p>
        </CardContent>
      </Card>
    );
  }

  if (loading && messages.length === 0) {
    return (
      <Card className="h-full">
        <CardContent className="flex items-center justify-center h-full">
          <div className="flex items-center gap-2">
            <Loader2 className="h-4 w-4 animate-spin" />
            <span>Loading messages...</span>
          </div>
        </CardContent>
      </Card>
    );
  }

  if (error) {
    return (
      <Card className="h-full border-red-200 bg-red-50">
        <CardContent className="flex items-center justify-center h-full">
          <p className="text-red-700">{error}</p>
        </CardContent>
      </Card>
    );
  }

  return (
    <Card className="h-full flex flex-col">
      <CardHeader className="border-b p-4">
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-3">
            {room && getRoomIcon(room)}
            <div>
              <CardTitle className="text-lg">
                {room?.type === 'd' 
                  ? `Direct message with ${room?.display_name || 'Unknown User'}`
                  : room?.display_name || room?.fname || room?.name || 'Unnamed Room'
                }
              </CardTitle>
              {room?.description && room?.type !== 'd' && (
                <p className="text-sm text-muted-foreground">{room.description}</p>
              )}
              {/* Only show participants for non-direct messages since DM names are already in the title */}
              {room?.participants && room.participants.length > 0 && room?.type !== 'd' && (
                <p className="text-xs text-muted-foreground">
                  {room.participants.map(p => p.name || p.username).join(', ')}
                </p>
              )}
            </div>
          </div>
          
          <div className="flex items-center gap-2">
            <Button
              variant="outline"
              size="sm"
              onClick={() => setShowSearch(!showSearch)}
            >
              <Search className="h-4 w-4" />
            </Button>
           
          </div>
        </div>
        
        {showSearch && (
          <div className="flex gap-2 mt-2">
            <Input
              placeholder="Search messages..."
              value={searchQuery}
              onChange={(e) => setSearchQuery(e.target.value)}
              onKeyPress={(e) => e.key === 'Enter' && searchMessages()}
            />
            <Button onClick={searchMessages} size="sm">Search</Button>
          </div>
        )}
      </CardHeader>
      
      <CardContent className="flex-1 p-0 overflow-hidden">
        <div 
          ref={messagesContainerRef}
          className="h-full overflow-y-auto p-4"
        >
          {hasMore && messages.length > 0 && (
            <div className="text-center mb-4">
              <Button
                variant="outline"
                size="sm"
                onClick={loadMoreMessages}
                disabled={loadingMore}
              >
                {loadingMore ? (
                  <Loader2 className="h-4 w-4 animate-spin mr-2" />
                ) : (
                  <ChevronUp className="h-4 w-4 mr-2" />
                )}
                Load older messages
              </Button>
            </div>
          )}
          
          {messages.length === 0 ? (
            <div className="text-center text-muted-foreground">
              No messages in this room
            </div>
          ) : (
            <div className="space-y-1">
              {messages.map((message, index) => renderMessage(message, index))}
            </div>
          )}
          
          <div ref={messagesEndRef} />
        </div>
      </CardContent>
    </Card>
  );
} 
