import React, {
  useState,
  useCallback,
  useMemo,
  useEffect,
  useRef,
} from 'react';
import Box from '@mui/material/Box';
import Paper from '@mui/material/Paper';
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
import useMediaQuery from '@mui/material/useMediaQuery';
import {
  Chat as ChatIcon,
  Edit as ComposeIcon,
  KeyboardArrowUp as ExpandIcon,
  KeyboardArrowDown as CollapseIcon,
} from '@mui/icons-material';
import { Trans } from '@lingui/macro';
import {
  ChatResponsiveSettings,
  ChatMessage,
  CallType,
} from '../../types/chat';
import useChatWebSocket from '../../hooks/useChatWebSocket';
import useChatUsers from '../../hooks/useChatUsers';
import useChatConversations from '../../hooks/useChatConversations';
import useChatCall from '../../hooks/useChatCall';
import ChatBox from './ChatBox';
import ChatUserList from './ChatUserList';
import CallModal from './CallModal';

interface ChatContainerProps {
  currentUserId?: number;
}

const ChatContainer: React.FC<ChatContainerProps> = ({ currentUserId }) => {
  // Responsive breakpoints
  const isDesktop = useMediaQuery('(min-width: 1025px)');
  const isMobile = useMediaQuery('(max-width: 767px)');

  // State for showing user list
  const [showUserList, setShowUserList] = useState(false);
  const [typingUsers, setTypingUsers] = useState<Record<string, number[]>>({});

  // Responsive settings
  const responsiveSettings: ChatResponsiveSettings = useMemo(() => {
    if (isDesktop) {
      return {
        boxWidth: 320,
        boxHeight: 450,
        minimizedHeight: 44,
        maxVisibleBoxes: 3,
        isMobile: false,
      };
    }
    // Tablet
    return {
      boxWidth: 280,
      boxHeight: 400,
      minimizedHeight: 44,
      maxVisibleBoxes: 2,
      isMobile: false,
    };
  }, [isDesktop]);

  // Ref for forwarding WebSocket events to conversations hook
  const conversationsRef = React.useRef<{
    handleIncomingMessage?: (message: ChatMessage) => void;
    handleConversationCreated?: (
      conversationId: string,
      recipientUserId: number,
    ) => void;
  }>({});

  // Ref to refresh users function (to avoid dependency issues)
  const refreshUsersRef = useRef<() => void>(() => {});

  // Track open conversation IDs for determining when to refresh unread counts
  const openConversationIds = useRef<Set<string>>(new Set());

  // Audio element ref for notification sound
  const notificationAudioRef = useRef<HTMLAudioElement | null>(null);

  // Initialize audio element on mount
  useEffect(() => {
    const audio = document.createElement('audio');
    audio.src = '/sounds/notification-message-tasko.mp3';
    audio.preload = 'auto';
    audio.volume = 0.5;
    document.body.appendChild(audio);
    notificationAudioRef.current = audio;

    return () => {
      if (notificationAudioRef.current) {
        document.body.removeChild(notificationAudioRef.current);
      }
    };
  }, []);

  // Function to play notification sound
  const playNotificationSound = useCallback(() => {
    const audio = notificationAudioRef.current;
    if (!audio) return;

    audio.currentTime = 0;
    const playPromise = audio.play();
    if (playPromise !== undefined) {
      playPromise.catch((err) => {
        console.error('[ChatContainer] Could not play notification sound:', err);
      });
    }
  }, []);

  // WebSocket connection with event handlers
  const handleIncomingMessage = useCallback(
    (message: ChatMessage) => {
      // Forward to useChatConversations
      conversationsRef.current?.handleIncomingMessage?.(message);

      // Play notification sound for messages from other users
      if (message.senderId !== currentUserId) {
        playNotificationSound();
      }

      // Refresh unread counts if message is for a conversation that is not currently open
      if (!openConversationIds.current.has(message.conversationId)) {
        refreshUsersRef.current();
      }
    },
    [currentUserId, playNotificationSound],
  );

  const handleTyping = useCallback(
    (conversationId: string, userId: number, isTyping: boolean) => {
      setTypingUsers((prev) => {
        const current = prev[conversationId] || [];
        if (isTyping) {
          if (!current.includes(userId)) {
            return { ...prev, [conversationId]: [...current, userId] };
          }
        } else {
          return {
            ...prev,
            [conversationId]: current.filter((id) => id !== userId),
          };
        }
        return prev;
      });

      // Clear typing after 5 seconds
      if (isTyping) {
        setTimeout(() => {
          setTypingUsers((prev) => ({
            ...prev,
            [conversationId]: (prev[conversationId] || []).filter(
              (id) => id !== userId,
            ),
          }));
        }, 5000);
      }
    },
    [],
  );

  const handleConversationUpdate = useCallback(
    (conversationId: string, data: any) => {
      if (data.type === 'new' && data.participants) {
        const recipientParticipant = data.participants.find(
          (p: any) => parseInt(p.externalUserId, 10) !== currentUserId,
        );
        if (recipientParticipant) {
          const recipientUserId = parseInt(
            recipientParticipant.externalUserId,
            10,
          );
          conversationsRef.current?.handleConversationCreated?.(
            conversationId,
            recipientUserId,
          );
        }
      }
    },
    [currentUserId],
  );

  const {
    connected: wsConnected,
    sendMessage: wsSendMessage,
    createAndSendMessage: wsCreateAndSend,
    sendTyping: wsSendTyping,
    markAsRead: wsMarkAsRead,
    onlineUsers,
    joinConversation: wsJoinConversation,
    chatToken,
    chatServerUrl,
    socket,
  } = useChatWebSocket({
    onMessage: handleIncomingMessage,
    onTyping: handleTyping,
    onConversationUpdate: handleConversationUpdate,
  });

  // Users list (with conversations)
  const {
    users,
    loading: usersLoading,
    totalUnreadCount,
    refresh: refreshUsers,
  } = useChatUsers(onlineUsers, currentUserId);

  // Helper to get user info for calls
  const getUserInfo = useCallback(
    (userId: number) => {
      const user = users.find((u) => u.id === userId);
      if (user) {
        return { name: user.name, avatar: user.avatar };
      }
      return undefined;
    },
    [users],
  );

  // Call functionality
  const {
    callState,
    startCall,
    acceptCall,
    declineCall,
    endCall,
    toggleMute,
    toggleVideo,
    toggleSpeaker,
  } = useChatCall({
    socket,
    currentUserId,
    getUserInfo,
  });

  // Conversations management
  const {
    openChats,
    openChat,
    closeChat,
    minimizeChat,
    expandChat,
    messages,
    loadingMessages,
    sendMessage,
    handleIncomingMessage: handleMessage,
    handleConversationCreated,
    loadMoreMessages,
    hasMoreMessages,
  } = useChatConversations({
    currentUserId,
    maxVisibleChats: responsiveSettings.maxVisibleBoxes,
    wsConnected,
    wsSendMessage,
    wsCreateAndSend,
    wsJoinConversation,
    wsMarkAsRead,
    chatServerUrl: chatServerUrl ?? undefined,
    chatToken: chatToken ?? undefined,
  });

  // Store ref to conversations for WebSocket callbacks
  useEffect(() => {
    conversationsRef.current = {
      handleIncomingMessage: handleMessage,
      handleConversationCreated,
    };
  }, [handleMessage, handleConversationCreated]);

  // Keep refreshUsers ref updated
  useEffect(() => {
    refreshUsersRef.current = refreshUsers;
  }, [refreshUsers]);

  // Track open (expanded) conversation IDs to know when to refresh unread counts
  useEffect(() => {
    openConversationIds.current = new Set(
      openChats
        .filter((chat) => !chat.minimized)
        .map((chat) => chat.conversationId),
    );
  }, [openChats]);

  // Handle user selection from user list
  const handleSelectUser = useCallback(
    async (userId: number, existingConversationId?: string) => {
      setShowUserList(false);
      const user = users.find((u) => u.id === userId);
      await openChat(userId, existingConversationId, user?.name, user?.avatar);
    },
    [openChat, users],
  );

  // Handle sending message
  const handleSendMessage = useCallback(
    (conversationId: string, content: string) => {
      sendMessage(conversationId, content);
    },
    [sendMessage],
  );

  // Handle typing indicator
  const handleTypingIndicator = useCallback(
    (conversationId: string, isTyping: boolean) => {
      if (!conversationId.startsWith('pending_')) {
        wsSendTyping(conversationId, isTyping);
      }
    },
    [wsSendTyping],
  );

  // Toggle user list
  const toggleUserList = useCallback(() => {
    setShowUserList((prev) => !prev);
  }, []);

  // Handle starting a call from a chat box
  const handleStartCall = useCallback(
    (userId: number, type: CallType) => {
      startCall(userId, type);
    },
    [startCall],
  );

  // Chat boxes start to the left of the dock
  const chatBoxBaseOffset = 16 + responsiveSettings.boxWidth + 8;

  // Don't render on mobile - must be after all hooks
  if (isMobile) {
    return null;
  }

  return (
    <>
      {/* Messaging Dock */}
      <Paper
        elevation={4}
        sx={{
          position: 'fixed',
          bottom: 0,
          right: 16,
          width: responsiveSettings.boxWidth,
          height: showUserList
            ? responsiveSettings.boxHeight
            : responsiveSettings.minimizedHeight,
          borderRadius: '8px 8px 0 0',
          overflow: 'hidden',
          display: 'flex',
          flexDirection: 'column',
          zIndex: 1300,
          transition: 'height 0.2s ease-in-out',
        }}
      >
        {/* Dock Header */}
        <Box
          onClick={toggleUserList}
          role="button"
          tabIndex={0}
          aria-expanded={showUserList}
          aria-label="Messaging"
          onKeyDown={(e) => {
            if (e.key === 'Enter' || e.key === ' ') {
              e.preventDefault();
              toggleUserList();
            }
          }}
          sx={{
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'space-between',
            px: 1.5,
            minHeight: responsiveSettings.minimizedHeight,
            backgroundColor: 'primary.main',
            color: 'primary.contrastText',
            cursor: 'pointer',
            flexShrink: 0,
            userSelect: 'none',
            '&:hover': {
              backgroundColor: 'primary.dark',
            },
          }}
        >
          <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
            <ChatIcon sx={{ fontSize: 20 }} />
            <Typography variant="subtitle2" fontWeight={600}>
              <Trans>Nachrichten</Trans>
            </Typography>
            {totalUnreadCount > 0 && (
              <Box
                sx={{
                  backgroundColor: 'error.main',
                  color: 'error.contrastText',
                  borderRadius: '10px',
                  fontSize: '11px',
                  fontWeight: 600,
                  minWidth: 20,
                  height: 20,
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  px: 0.5,
                }}
              >
                {totalUnreadCount > 99 ? '99+' : totalUnreadCount}
              </Box>
            )}
          </Box>
          <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
            <IconButton
              size="small"
              onClick={(e) => {
                e.stopPropagation();
                if (!showUserList) setShowUserList(true);
              }}
              aria-label="Neue Nachricht verfassen"
              sx={{
                color: 'primary.contrastText',
                '&:hover': { backgroundColor: 'rgba(255,255,255,0.15)' },
              }}
            >
              <ComposeIcon sx={{ fontSize: 18 }} />
            </IconButton>
            <Box
              sx={{
                color: 'primary.contrastText',
                display: 'flex',
                alignItems: 'center',
              }}
            >
              {showUserList ? (
                <CollapseIcon sx={{ fontSize: 20 }} />
              ) : (
                <ExpandIcon sx={{ fontSize: 20 }} />
              )}
            </Box>
          </Box>
        </Box>

        {/* Embedded Conversation List */}
        <ChatUserList
          users={users}
          loading={usersLoading}
          currentUserId={currentUserId}
          responsiveSettings={responsiveSettings}
          rightOffset={0}
          onSelectUser={handleSelectUser}
          onClose={() => setShowUserList(false)}
          embedded
        />
      </Paper>

      {/* Chat boxes - positioned to the left of dock */}
      {openChats.map((chatState) => {
        const positionOffset =
          chatState.position * (responsiveSettings.boxWidth + 8);
        const rightOffset = chatBoxBaseOffset + positionOffset;

        // Get other participant ID for calls (direct chats only)
        const otherParticipant = chatState.conversation?.participants.find(
          (p) => p.id !== currentUserId,
        );

        return (
          <ChatBox
            key={chatState.conversationId}
            chatState={chatState}
            messages={messages[chatState.conversationId] || []}
            currentUserId={currentUserId || 0}
            loading={loadingMessages[chatState.conversationId]}
            typingUsers={typingUsers[chatState.conversationId]}
            responsiveSettings={responsiveSettings}
            rightOffset={rightOffset}
            hasMore={hasMoreMessages(chatState.conversationId)}
            onlineUsers={onlineUsers}
            onMinimize={() => minimizeChat(chatState.conversationId)}
            onExpand={() => expandChat(chatState.conversationId)}
            onClose={() => closeChat(chatState.conversationId)}
            onSendMessage={(content) =>
              handleSendMessage(chatState.conversationId, content)
            }
            onTyping={(isTyping) =>
              handleTypingIndicator(chatState.conversationId, isTyping)
            }
            onLoadMore={() => loadMoreMessages(chatState.conversationId)}
            onCall={
              otherParticipant
                ? (type) => handleStartCall(otherParticipant.id, type)
                : undefined
            }
          />
        );
      })}

      {/* Call Modal */}
      <CallModal
        callState={callState}
        onAccept={acceptCall}
        onDecline={declineCall}
        onEnd={endCall}
        onToggleMute={toggleMute}
        onToggleVideo={toggleVideo}
        onToggleSpeaker={toggleSpeaker}
      />
    </>
  );
};

export default ChatContainer;
