import { useState, useEffect, useCallback, useMemo } from 'react';
import axios from 'axios';
import {
  ChatUserWithConversation,
  ChatMessage,
  ChatToken,
  UseChatUsersReturn,
} from '../types/chat';

interface ConversationFromServer {
  id: string;
  type: string;
  name?: string;
  participants: Array<{
    externalUserId: string;
    name: string;
    avatar?: string;
  }>;
  lastMessage?: {
    id: string;
    content: string;
    senderId: string;
    createdAt: string;
    type?: string;
  };
  unreadCount?: number;
}

interface ConversationsApiResponse {
  conversations: ConversationFromServer[];
  nextCursor?: string;
}

export const useChatUsers = (
  onlineUsers?: Set<number>,
  currentUserId?: number
): UseChatUsersReturn => {
  const [users, setUsers] = useState<ChatUserWithConversation[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  // Fetch available users and conversations
  const fetchData = useCallback(async () => {
    setLoading(true);
    setError(null);

    try {
      // Fetch users and token in parallel for faster loading
      const [usersResponse, tokenResponse] = await Promise.all([
        axios.get<
          Array<{
            id: number;
            name: string;
            email: string | null;
            avatar: string | null;
          }>
        >('/zeiterfassung/chat/users'),
        axios.get<ChatToken>('/zeiterfassung/chat/token').catch(() => null),
      ]);

      // Try to get conversations from chat server using JWT
      let conversationsList: ConversationFromServer[] = [];

      if (tokenResponse?.data) {
        try {
          const { token, chatServerUrl } = tokenResponse.data;

          // Fetch conversations directly from chat server
          const conversationsResponse = await axios.get<ConversationsApiResponse>(
            `${chatServerUrl}/api/conversations`,
            {
              headers: {
                Authorization: `Bearer ${token}`,
              },
            }
          );

          conversationsList = conversationsResponse.data.conversations || [];
        } catch (convErr) {
          console.warn('[Chat Users] Could not fetch conversations:', convErr);
          // Continue without conversations - users will still be shown
        }
      }

      // Create a map of user ID to their direct conversation
      const userConversationMap = new Map<
        number,
        { conversationId: string; lastMessage?: ChatMessage; unreadCount: number }
      >();

      // Process direct conversations
      conversationsList.forEach((conv) => {
        if (conv.type?.toUpperCase() === 'DIRECT') {
          // Find the other participant (not the current user)
          const otherParticipant = conv.participants.find(
            (p) => parseInt(p.externalUserId, 10) !== currentUserId
          );

          if (otherParticipant) {
            const otherUserId = parseInt(otherParticipant.externalUserId, 10);
            userConversationMap.set(otherUserId, {
              conversationId: conv.id,
              lastMessage: conv.lastMessage
                ? {
                    id: conv.lastMessage.id,
                    conversationId: conv.id,
                    senderId: parseInt(conv.lastMessage.senderId, 10),
                    content: conv.lastMessage.content,
                    timestamp: conv.lastMessage.createdAt,
                    status: 'delivered',
                    type: (conv.lastMessage.type as 'text' | 'image' | 'file') || 'text',
                  }
                : undefined,
              unreadCount: conv.unreadCount || 0,
            });
          }
        }
      });

      // Merge users with their conversation data
      const fetchedUsers: ChatUserWithConversation[] = usersResponse.data.map((user) => {
        const convData = userConversationMap.get(user.id);
        return {
          id: user.id,
          name: user.name,
          avatar: user.avatar,
          email: user.email ?? undefined,
          isOnline: onlineUsers?.has(user.id) ?? false,
          conversationId: convData?.conversationId,
          lastMessage: convData?.lastMessage,
          unreadCount: convData?.unreadCount,
        };
      });

      setUsers(fetchedUsers);
    } catch (err) {
      console.error('[Chat Users] Failed to fetch data:', err);
      setError('Failed to load users');
    } finally {
      setLoading(false);
    }
  }, [onlineUsers, currentUserId]);

  // Update online status when onlineUsers changes
  useEffect(() => {
    if (onlineUsers) {
      setUsers((prev) =>
        prev.map((user) => ({
          ...user,
          isOnline: onlineUsers.has(user.id),
        }))
      );
    }
  }, [onlineUsers]);

  // Fetch data on mount
  useEffect(() => {
    fetchData();
  }, [fetchData]);

  // Search/filter users
  const searchUsers = useCallback(
    (query: string): ChatUserWithConversation[] => {
      if (!query.trim()) {
        return users;
      }

      const lowerQuery = query.toLowerCase();
      return users.filter(
        (user) =>
          user.name.toLowerCase().includes(lowerQuery) ||
          (user.email && user.email.toLowerCase().includes(lowerQuery))
      );
    },
    [users]
  );

  // Sort users: users with conversations first (by last message time), then online, then alphabetically
  const sortedUsers = useMemo(() => {
    return [...users].sort((a, b) => {
      // Users with conversations first
      if (a.lastMessage && !b.lastMessage) return -1;
      if (!a.lastMessage && b.lastMessage) return 1;

      // If both have conversations, sort by last message time (newest first)
      if (a.lastMessage && b.lastMessage) {
        return (
          new Date(b.lastMessage.timestamp).getTime() - new Date(a.lastMessage.timestamp).getTime()
        );
      }

      // Online users next
      if (a.isOnline && !b.isOnline) return -1;
      if (!a.isOnline && b.isOnline) return 1;

      // Then alphabetically
      return a.name.localeCompare(b.name);
    });
  }, [users]);

  // Calculate total unread count across all conversations
  const totalUnreadCount = useMemo(() => {
    return users.reduce((total, user) => total + (user.unreadCount || 0), 0);
  }, [users]);

  return {
    users: sortedUsers,
    loading,
    error,
    refresh: fetchData,
    searchUsers,
    totalUnreadCount,
  };
};

export default useChatUsers;
