{"version":3,"sources":["../src/components/Chat/Chat.tsx","../src/hooks/useChat.ts","../src/hooks/useChatRooms.ts"],"sourcesContent":["import { useState, useEffect, useCallback, useRef } from 'react';\nimport {\n  PaperPlaneTiltIcon,\n  XIcon,\n  PlusIcon,\n  UsersIcon,\n} from '@phosphor-icons/react';\nimport Text from '../Text/Text';\nimport Button from '../Button/Button';\nimport Input from '../Input/Input';\nimport Modal from '../Modal/Modal';\nimport { SkeletonText, SkeletonRounded } from '../Skeleton/Skeleton';\nimport EmptyState from '../EmptyState/EmptyState';\nimport { useChat } from '../../hooks/useChat';\nimport { useChatRooms } from '../../hooks/useChatRooms';\nimport {\n  PROFILE_ROLES,\n  CHAT_MESSAGE_TYPES,\n  type ChatApiClient,\n  type ChatRoomWithDetails,\n  type ChatMessage,\n  type ChatParticipant,\n  type ChatUser,\n} from '../../types/chat';\nimport { cn } from '../../utils/utils';\n\n/**\n * Props for the Chat component\n */\nexport interface ChatProps {\n  /** API client for REST calls */\n  apiClient: ChatApiClient;\n  /** WebSocket URL for real-time messaging */\n  wsUrl: string;\n  /** JWT authentication token */\n  token: string;\n  /** Current user's userInstitutionId */\n  userId: string;\n  /** Current user's display name */\n  userName: string;\n  /** Current user's profile photo URL */\n  userPhoto?: string | null;\n  /** Current user's role */\n  userRole: PROFILE_ROLES;\n  /** Additional CSS classes */\n  className?: string;\n  /** Initial room ID to open (from URL) */\n  initialRoomId?: string;\n  /** Callback when room changes (for URL navigation) */\n  onRoomChange?: (roomId: string) => void;\n  /** Callback when returning to room list */\n  onBackToList?: () => void;\n}\n\n/**\n * Chat view states\n */\ntype ChatView = 'list' | 'room' | 'create';\n\n/**\n * Room item component for the list\n */\nconst RoomItem = ({\n  room,\n  onClick,\n  isActive,\n}: {\n  room: ChatRoomWithDetails;\n  onClick: () => void;\n  isActive: boolean;\n}) => (\n  <Button\n    variant=\"link\"\n    onClick={onClick}\n    className={cn(\n      'w-full p-3 rounded-lg text-left transition-colors justify-start h-auto',\n      'hover:bg-background-100',\n      isActive && 'bg-primary-50 border-l-4 border-primary-500'\n    )}\n  >\n    <div className=\"flex items-start gap-3 w-full\">\n      <div className=\"w-10 h-10 rounded-full bg-primary-100 flex items-center justify-center flex-shrink-0\">\n        <UsersIcon size={20} className=\"text-primary-600\" />\n      </div>\n      <div className=\"flex-1 min-w-0\">\n        <Text size=\"sm\" weight=\"semibold\" className=\"text-text-900 truncate\">\n          {room.name}\n        </Text>\n        {room.lastMessage && (\n          <Text size=\"xs\" className=\"text-text-500 truncate mt-1\">\n            {room.lastMessage.senderName}: {room.lastMessage.content}\n          </Text>\n        )}\n        <Text size=\"xs\" className=\"text-text-400 mt-1\">\n          {room.participantCount} participantes\n        </Text>\n      </div>\n    </div>\n  </Button>\n);\n\n/**\n * Message bubble component\n */\nconst MessageBubble = ({\n  message,\n  isOwn,\n}: {\n  message: ChatMessage;\n  isOwn: boolean;\n}) => (\n  <div className={cn('flex gap-2 mb-3', isOwn && 'flex-row-reverse')}>\n    {!isOwn && (\n      <div className=\"w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center flex-shrink-0\">\n        {message.senderPhoto ? (\n          <img\n            src={message.senderPhoto}\n            alt={message.senderName}\n            className=\"w-8 h-8 rounded-full object-cover\"\n          />\n        ) : (\n          <Text size=\"xs\" weight=\"bold\" className=\"text-gray-600\">\n            {message.senderName.charAt(0).toUpperCase()}\n          </Text>\n        )}\n      </div>\n    )}\n    <div className={cn('max-w-[70%]', isOwn && 'items-end')}>\n      {!isOwn && (\n        <Text size=\"xs\" className=\"text-text-500 mb-1\">\n          {message.senderName}\n        </Text>\n      )}\n      <div\n        className={cn(\n          'px-4 py-2 rounded-2xl',\n          isOwn\n            ? 'bg-primary-500 text-white rounded-br-md'\n            : 'bg-background-100 text-text-900 rounded-bl-md'\n        )}\n      >\n        <Text size=\"sm\">{message.content}</Text>\n      </div>\n      <Text\n        size=\"xs\"\n        className={cn('text-text-400 mt-1', isOwn && 'text-right')}\n      >\n        {new Date(message.createdAt).toLocaleTimeString('pt-BR', {\n          hour: '2-digit',\n          minute: '2-digit',\n        })}\n      </Text>\n    </div>\n  </div>\n);\n\n/**\n * Participant item component\n */\nconst ParticipantItem = ({ participant }: { participant: ChatParticipant }) => (\n  <div className=\"flex items-center gap-2 py-2\">\n    <div className=\"relative\">\n      <div className=\"w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center\">\n        {participant.photo ? (\n          <img\n            src={participant.photo}\n            alt={participant.name}\n            className=\"w-8 h-8 rounded-full object-cover\"\n          />\n        ) : (\n          <Text size=\"xs\" weight=\"bold\" className=\"text-gray-600\">\n            {participant.name.charAt(0).toUpperCase()}\n          </Text>\n        )}\n      </div>\n      {participant.isOnline && (\n        <div className=\"absolute bottom-0 right-0 w-3 h-3 bg-green-500 rounded-full border-2 border-white\" />\n      )}\n    </div>\n    <div className=\"flex-1 min-w-0\">\n      <Text size=\"sm\" className=\"text-text-900 truncate\">\n        {participant.name}\n      </Text>\n      <Text size=\"xs\" className=\"text-text-500\">\n        {participant.role}\n      </Text>\n    </div>\n  </div>\n);\n\n/**\n * User selector for creating new rooms\n */\nconst UserSelector = ({\n  users,\n  selectedIds,\n  onToggle,\n}: {\n  users: ChatUser[];\n  selectedIds: Set<string>;\n  onToggle: (id: string) => void;\n}) => (\n  <div className=\"space-y-2 max-h-64 overflow-y-auto\">\n    {users.map((user) => (\n      <Button\n        key={user.userInstitutionId}\n        variant=\"link\"\n        onClick={() => onToggle(user.userInstitutionId)}\n        className={cn(\n          'w-full flex items-center gap-3 p-3 rounded-lg transition-colors justify-start h-auto',\n          selectedIds.has(user.userInstitutionId)\n            ? 'bg-primary-50 border border-primary-500'\n            : 'bg-background-50 hover:bg-background-100 border border-transparent'\n        )}\n      >\n        <div className=\"w-10 h-10 rounded-full bg-gray-200 flex items-center justify-center\">\n          {user.photo ? (\n            <img\n              src={user.photo}\n              alt={user.name}\n              className=\"w-10 h-10 rounded-full object-cover\"\n            />\n          ) : (\n            <Text size=\"sm\" weight=\"bold\" className=\"text-gray-600\">\n              {user.name.charAt(0).toUpperCase()}\n            </Text>\n          )}\n        </div>\n        <div className=\"flex-1 text-left\">\n          <Text size=\"sm\" weight=\"medium\" className=\"text-text-900\">\n            {user.name}\n          </Text>\n          <Text size=\"xs\" className=\"text-text-500\">\n            {user.profileName}\n          </Text>\n        </div>\n        <div\n          className={cn(\n            'w-5 h-5 rounded-full border-2 flex items-center justify-center',\n            selectedIds.has(user.userInstitutionId)\n              ? 'bg-primary-500 border-primary-500'\n              : 'border-gray-300'\n          )}\n        >\n          {selectedIds.has(user.userInstitutionId) && (\n            <div className=\"w-2 h-2 bg-white rounded-full\" />\n          )}\n        </div>\n      </Button>\n    ))}\n  </div>\n);\n\n/**\n * Main Chat component\n *\n * Provides complete chat functionality:\n * - List of chat rooms\n * - Create new chat rooms\n * - Real-time messaging within rooms\n *\n * @example\n * ```tsx\n * <Chat\n *   apiClient={api}\n *   wsUrl=\"wss://api.example.com/chat/ws\"\n *   token={authToken}\n *   userId={user.userInstitutionId}\n *   userName={user.name}\n *   userPhoto={user.photo}\n *   userRole=\"teacher\"\n * />\n * ```\n */\nexport function Chat(props: Readonly<ChatProps>) {\n  const { userId, token } = props;\n\n  // Show loading state if user info is not available\n  if (!userId || !token) {\n    return (\n      <div className=\"flex items-center justify-center h-96\">\n        <Text size=\"sm\" className=\"text-text-500\">\n          Carregando...\n        </Text>\n      </div>\n    );\n  }\n\n  return <ChatContent {...props} />;\n}\n\n/**\n * Internal Chat content component (rendered when user info is available)\n */\nfunction ChatContent({\n  apiClient,\n  wsUrl,\n  token,\n  userId,\n  userName,\n  userPhoto,\n  userRole,\n  className,\n  initialRoomId,\n  onRoomChange,\n  onBackToList,\n}: Readonly<ChatProps>) {\n  const [view, setView] = useState<ChatView>('list');\n  const [selectedRoom, setSelectedRoom] = useState<ChatRoomWithDetails | null>(\n    null\n  );\n  const [selectedUserIds, setSelectedUserIds] = useState<Set<string>>(\n    new Set()\n  );\n  const [messageInput, setMessageInput] = useState('');\n  const [showCreateModal, setShowCreateModal] = useState(false);\n  const hasHandledInitialRoomRef = useRef(false);\n\n  // Hooks for REST operations\n  const {\n    rooms,\n    availableUsers,\n    loading: roomsLoading,\n    error: roomsError,\n    fetchRooms,\n    fetchAvailableUsers,\n    createRoom,\n  } = useChatRooms({ apiClient });\n\n  // Hook for WebSocket (only when in a room)\n  const {\n    isConnected,\n    messages,\n    participants,\n    sendMessage,\n    error: chatError,\n  } = useChat({\n    wsUrl,\n    token,\n    roomId: selectedRoom?.id || '',\n    userId,\n    onConnect: () => console.log('Connected to chat'),\n    onDisconnect: () => console.log('Disconnected from chat'),\n    onError: (err) => console.error('Chat error:', err),\n  });\n\n  // Get role label for display\n  const getRoleLabel = () => {\n    return userRole === PROFILE_ROLES.TEACHER ? 'Professor' : 'Aluno';\n  };\n\n  // Fetch rooms on mount\n  useEffect(() => {\n    fetchRooms();\n  }, [fetchRooms]);\n\n  // Handle initial room from URL\n  useEffect(() => {\n    // Only handle initial room once\n    if (hasHandledInitialRoomRef.current) {\n      return;\n    }\n\n    // Wait for rooms to load before trying to find the initial room\n    if (!initialRoomId || roomsLoading) {\n      return;\n    }\n\n    // Only proceed if rooms have been loaded (not initial empty state)\n    if (rooms?.length > 0) {\n      const room = rooms.find((r) => r.id === initialRoomId);\n      if (room) {\n        hasHandledInitialRoomRef.current = true;\n        setSelectedRoom(room);\n        setView('room');\n      } else {\n        // Room not found in user's rooms, redirect to list\n        hasHandledInitialRoomRef.current = true;\n        onBackToList?.();\n      }\n    } else if (rooms !== undefined && !roomsLoading) {\n      // Rooms loaded but empty, or room not found\n      hasHandledInitialRoomRef.current = true;\n      onBackToList?.();\n    }\n  }, [initialRoomId, rooms, roomsLoading, onBackToList]);\n\n  // Handle room selection\n  const handleSelectRoom = useCallback(\n    (room: ChatRoomWithDetails) => {\n      setSelectedRoom(room);\n      setView('room');\n      onRoomChange?.(room.id);\n    },\n    [onRoomChange]\n  );\n\n  // Handle create room\n  const handleOpenCreateModal = useCallback(async () => {\n    await fetchAvailableUsers();\n    setSelectedUserIds(new Set());\n    setShowCreateModal(true);\n  }, [fetchAvailableUsers]);\n\n  const handleToggleUser = useCallback((id: string) => {\n    setSelectedUserIds((prev) => {\n      const next = new Set(prev);\n      if (next.has(id)) {\n        next.delete(id);\n      } else {\n        next.add(id);\n      }\n      return next;\n    });\n  }, []);\n\n  const handleCreateRoom = useCallback(async () => {\n    if (selectedUserIds.size === 0) return;\n\n    const room = await createRoom(Array.from(selectedUserIds));\n    if (room) {\n      setShowCreateModal(false);\n      setSelectedUserIds(new Set());\n      // Navigate to the new room\n      onRoomChange?.(room.id);\n    }\n  }, [selectedUserIds, createRoom, onRoomChange]);\n\n  // Handle send message\n  const handleSendMessage = useCallback(() => {\n    if (!messageInput.trim()) return;\n    sendMessage(messageInput);\n    setMessageInput('');\n  }, [messageInput, sendMessage]);\n\n  // Handle back to list\n  const handleBackToList = useCallback(() => {\n    setSelectedRoom(null);\n    setView('list');\n    onBackToList?.();\n  }, [onBackToList]);\n\n  // Render messages content\n  const renderMessagesContent = () => {\n    if (chatError) {\n      return (\n        <div className=\"flex items-center justify-center h-full\">\n          <div className=\"text-center\">\n            <Text size=\"sm\" className=\"text-red-500 mb-2\">\n              Erro de conexao com o chat\n            </Text>\n            <Text size=\"xs\" className=\"text-text-500\">\n              Tentando reconectar...\n            </Text>\n          </div>\n        </div>\n      );\n    }\n\n    // Filter out system messages (user joined/left notifications)\n    const userMessages = messages?.filter(\n      (message) => message.messageType !== CHAT_MESSAGE_TYPES.SYSTEM\n    );\n\n    if (!userMessages?.length) {\n      return (\n        <div className=\"flex items-center justify-center h-full\">\n          <Text size=\"sm\" className=\"text-text-500\">\n            Nenhuma mensagem ainda. Comece a conversa!\n          </Text>\n        </div>\n      );\n    }\n\n    return userMessages.map((message) => (\n      <MessageBubble\n        key={message.id}\n        message={message}\n        isOwn={message.senderId === userId}\n      />\n    ));\n  };\n\n  // Render room list\n  const renderRoomList = () => (\n    <div className=\"flex flex-col h-full\">\n      <div className=\"p-4 border-b border-background-200 flex items-center justify-between\">\n        <div className=\"flex items-center gap-3\">\n          <div className=\"w-10 h-10 rounded-full bg-primary-100 flex items-center justify-center flex-shrink-0\">\n            {userPhoto ? (\n              <img\n                src={userPhoto}\n                alt={userName}\n                className=\"w-10 h-10 rounded-full object-cover\"\n              />\n            ) : (\n              <Text size=\"sm\" weight=\"bold\" className=\"text-primary-600\">\n                {userName.charAt(0).toUpperCase()}\n              </Text>\n            )}\n          </div>\n          <div>\n            <Text size=\"lg\" weight=\"bold\" className=\"text-text-900\">\n              Conversas\n            </Text>\n            <Text size=\"xs\" className=\"text-text-500\">\n              {userName} - {getRoleLabel()}\n            </Text>\n          </div>\n        </div>\n        <Button\n          variant=\"solid\"\n          size=\"small\"\n          onClick={handleOpenCreateModal}\n          iconLeft={<PlusIcon size={16} />}\n        >\n          Nova conversa\n        </Button>\n      </div>\n\n      <div className=\"flex-1 overflow-y-auto p-2\">\n        {roomsError && (\n          <div className=\"p-4 text-center\">\n            <Text size=\"sm\" className=\"text-red-500 mb-2\">\n              Erro ao carregar conversas\n            </Text>\n            <Button variant=\"outline\" size=\"small\" onClick={fetchRooms}>\n              Tentar novamente\n            </Button>\n          </div>\n        )}\n        {!roomsError && roomsLoading && (\n          <div className=\"space-y-3 p-2\">\n            {[1, 2, 3].map((i) => (\n              <div key={i} className=\"flex items-center gap-3\">\n                <SkeletonRounded className=\"w-10 h-10\" />\n                <div className=\"flex-1\">\n                  <SkeletonText className=\"w-3/4 h-4 mb-2\" />\n                  <SkeletonText className=\"w-1/2 h-3\" />\n                </div>\n              </div>\n            ))}\n          </div>\n        )}\n        {!roomsError && !roomsLoading && !rooms?.length && (\n          <EmptyState\n            title=\"Nenhuma conversa\"\n            description=\"Comece uma nova conversa clicando no botao acima\"\n          />\n        )}\n        {!roomsError && !roomsLoading && !!rooms?.length && (\n          <div className=\"space-y-1\">\n            {rooms.map((room) => (\n              <RoomItem\n                key={room.id}\n                room={room}\n                onClick={() => handleSelectRoom(room)}\n                isActive={selectedRoom?.id === room.id}\n              />\n            ))}\n          </div>\n        )}\n      </div>\n    </div>\n  );\n\n  // Render chat room\n  const renderChatRoom = () => {\n    if (!selectedRoom) return null;\n\n    return (\n      <div className=\"flex h-full\">\n        {/* Messages area */}\n        <div className=\"flex-1 flex flex-col\">\n          {/* Header */}\n          <div className=\"p-4 border-b border-background-200 flex items-center gap-3\">\n            <Button variant=\"link\" size=\"small\" onClick={handleBackToList}>\n              <XIcon size={20} />\n            </Button>\n            <div className=\"flex-1\">\n              <Text size=\"md\" weight=\"semibold\" className=\"text-text-900\">\n                {selectedRoom.name}\n              </Text>\n              <Text size=\"xs\" className=\"text-text-500\">\n                {isConnected ? 'Conectado' : 'Conectando...'}\n              </Text>\n            </div>\n          </div>\n\n          {/* Messages */}\n          <div className=\"flex-1 overflow-y-auto p-4\">\n            {renderMessagesContent()}\n          </div>\n\n          {/* Input */}\n          <div className=\"p-4 border-t border-background-200\">\n            <div className=\"flex gap-2\">\n              <Input\n                placeholder=\"Digite sua mensagem...\"\n                value={messageInput}\n                onChange={(e) => setMessageInput(e.target.value)}\n                onKeyDown={(e) => {\n                  if (e.key === 'Enter' && !e.shiftKey) {\n                    e.preventDefault();\n                    handleSendMessage();\n                  }\n                }}\n                className=\"flex-1\"\n              />\n              <Button\n                variant=\"solid\"\n                onClick={handleSendMessage}\n                disabled={!messageInput.trim() || !isConnected}\n              >\n                <PaperPlaneTiltIcon size={20} />\n              </Button>\n            </div>\n          </div>\n        </div>\n\n        {/* Participants sidebar */}\n        <div className=\"w-64 border-l border-background-200 p-4 hidden lg:block\">\n          <Text size=\"sm\" weight=\"semibold\" className=\"text-text-900 mb-3\">\n            Participantes ({participants?.length ?? 0})\n          </Text>\n          <div className=\"space-y-1\">\n            {participants?.map((participant) => (\n              <ParticipantItem\n                key={participant.userInstitutionId}\n                participant={participant}\n              />\n            ))}\n          </div>\n        </div>\n      </div>\n    );\n  };\n\n  return (\n    <div\n      className={cn(\n        'bg-background rounded-xl border border-background-200 h-[600px]',\n        className\n      )}\n    >\n      {view === 'list' && renderRoomList()}\n      {view === 'room' && renderChatRoom()}\n\n      {/* Create room modal */}\n      <Modal\n        isOpen={showCreateModal}\n        onClose={() => setShowCreateModal(false)}\n        title=\"Nova conversa\"\n      >\n        <div className=\"p-4\">\n          <Text size=\"sm\" className=\"text-text-600 mb-4\">\n            Selecione os participantes para iniciar uma conversa\n          </Text>\n\n          {roomsLoading && (\n            <div className=\"space-y-3\">\n              {[1, 2, 3].map((i) => (\n                <div key={i} className=\"flex items-center gap-3\">\n                  <SkeletonRounded className=\"w-10 h-10\" />\n                  <SkeletonText className=\"flex-1 h-4\" />\n                </div>\n              ))}\n            </div>\n          )}\n          {!roomsLoading && !availableUsers?.length && (\n            <Text size=\"sm\" className=\"text-text-500 text-center py-4\">\n              Nenhum usuario disponivel para chat\n            </Text>\n          )}\n          {!roomsLoading && !!availableUsers?.length && (\n            <UserSelector\n              users={availableUsers}\n              selectedIds={selectedUserIds}\n              onToggle={handleToggleUser}\n            />\n          )}\n\n          <div className=\"flex justify-end gap-2 mt-6\">\n            <Button variant=\"outline\" onClick={() => setShowCreateModal(false)}>\n              Cancelar\n            </Button>\n            <Button\n              variant=\"solid\"\n              onClick={handleCreateRoom}\n              disabled={selectedUserIds.size === 0 || roomsLoading}\n            >\n              Criar conversa\n            </Button>\n          </div>\n        </div>\n      </Modal>\n    </div>\n  );\n}\n\nexport default Chat;\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport type {\n  ChatMessage,\n  ChatParticipant,\n  WSServerMessage,\n  WSClientMessage,\n} from '../types/chat';\n\n/**\n * WebSocket connection states\n */\nexport const WS_STATES = {\n  CONNECTING: 0,\n  OPEN: 1,\n  CLOSING: 2,\n  CLOSED: 3,\n} as const;\n\n/**\n * Options for the useChat hook\n */\nexport interface UseChatOptions {\n  /** WebSocket URL (e.g., wss://api.example.com/chat/ws) */\n  wsUrl: string;\n  /** JWT authentication token */\n  token: string;\n  /** Chat room ID */\n  roomId: string;\n  /** Current user's userInstitutionId */\n  userId: string;\n  /** Callback when connection is established */\n  onConnect?: () => void;\n  /** Callback when connection is closed */\n  onDisconnect?: () => void;\n  /** Callback when an error occurs */\n  onError?: (error: Error) => void;\n  /** Auto-reconnect on disconnect (default: true) */\n  autoReconnect?: boolean;\n  /** Reconnect interval in ms (default: 3000) */\n  reconnectInterval?: number;\n  /** Max reconnect attempts (default: 5) */\n  maxReconnectAttempts?: number;\n}\n\n/**\n * Return type for the useChat hook\n */\nexport interface UseChatReturn {\n  /** Whether WebSocket is connected */\n  isConnected: boolean;\n  /** List of chat messages */\n  messages: ChatMessage[];\n  /** List of room participants */\n  participants: ChatParticipant[];\n  /** Send a text message */\n  sendMessage: (content: string) => void;\n  /** Leave the chat room */\n  leave: () => void;\n  /** Current error state */\n  error: Error | null;\n  /** Reconnect to the WebSocket */\n  reconnect: () => void;\n  /** Current user ID for identifying own messages */\n  currentUserId: string;\n}\n\n/**\n * Hook for managing WebSocket connection to a chat room\n *\n * Handles:\n * - WebSocket connection lifecycle\n * - Message sending/receiving\n * - Participant tracking\n * - Auto-reconnection\n *\n * @param options - Hook configuration options\n * @returns Chat state and actions\n *\n * @example\n * ```tsx\n * const {\n *   isConnected,\n *   messages,\n *   participants,\n *   sendMessage,\n *   error\n * } = useChat({\n *   wsUrl: 'wss://api.example.com/chat/ws',\n *   token: authToken,\n *   roomId: 'room-123',\n *   userId: 'user-456',\n *   onConnect: () => console.log('Connected!'),\n *   onError: (err) => console.error('Error:', err),\n * });\n *\n * const handleSend = () => {\n *   sendMessage('Hello, world!');\n * };\n * ```\n */\nexport function useChat({\n  wsUrl,\n  token,\n  roomId,\n  userId,\n  onConnect,\n  onDisconnect,\n  onError,\n  autoReconnect = true,\n  reconnectInterval = 3000,\n  maxReconnectAttempts = 5,\n}: UseChatOptions): UseChatReturn {\n  const [isConnected, setIsConnected] = useState(false);\n  const [messages, setMessages] = useState<ChatMessage[]>([]);\n  const [participants, setParticipants] = useState<ChatParticipant[]>([]);\n  const [error, setError] = useState<Error | null>(null);\n\n  const wsRef = useRef<WebSocket | null>(null);\n  const reconnectAttemptsRef = useRef(0);\n  const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(\n    null\n  );\n  const isManualDisconnectRef = useRef(false);\n  const isConnectingRef = useRef(false);\n  const connectRef = useRef<() => void>(() => {});\n\n  /**\n   * Send a WebSocket message\n   */\n  const sendWsMessage = useCallback((message: WSClientMessage) => {\n    if (wsRef.current?.readyState === WS_STATES.OPEN) {\n      wsRef.current.send(JSON.stringify(message));\n    }\n  }, []);\n\n  /**\n   * Send a text message\n   */\n  const sendMessage = useCallback(\n    (content: string) => {\n      const trimmedContent = content.trim();\n      if (!trimmedContent) return;\n\n      sendWsMessage({\n        type: 'message',\n        payload: { content: trimmedContent },\n      });\n    },\n    [sendWsMessage]\n  );\n\n  /**\n   * Leave the chat room\n   */\n  const leave = useCallback(() => {\n    isManualDisconnectRef.current = true;\n    sendWsMessage({ type: 'leave' });\n    wsRef.current?.close(1000, 'User left');\n  }, [sendWsMessage]);\n\n  /**\n   * Handle incoming WebSocket messages\n   */\n  const handleMessage = useCallback(\n    (event: MessageEvent) => {\n      try {\n        const data = JSON.parse(event.data) as WSServerMessage;\n\n        switch (data.type) {\n          case 'history':\n            if (data.payload.messages) {\n              setMessages(data.payload.messages);\n            }\n            break;\n\n          case 'participants':\n            if (data.payload.participants) {\n              setParticipants(data.payload.participants);\n            }\n            break;\n\n          case 'new_message':\n            if (data.payload.message) {\n              setMessages((prev) => [...prev, data.payload.message!]);\n            }\n            break;\n\n          case 'user_joined':\n            if (data.payload.user) {\n              const user = data.payload.user;\n              setParticipants((prev) => {\n                // Check if user already exists\n                const exists = prev.some(\n                  (p) => p.userInstitutionId === user.userInstitutionId\n                );\n                if (exists) {\n                  // Update online status\n                  return prev.map((p) =>\n                    p.userInstitutionId === user.userInstitutionId\n                      ? { ...p, isOnline: true }\n                      : p\n                  );\n                }\n                // Add new participant\n                return [\n                  ...prev,\n                  {\n                    userInstitutionId: user.userInstitutionId,\n                    name: user.name,\n                    photo: user.photo,\n                    role: user.role,\n                    isOnline: true,\n                  },\n                ];\n              });\n            }\n            break;\n\n          case 'user_left':\n            if (data.payload.user) {\n              const user = data.payload.user;\n              setParticipants((prev) =>\n                prev.map((p) =>\n                  p.userInstitutionId === user.userInstitutionId\n                    ? { ...p, isOnline: false }\n                    : p\n                )\n              );\n            }\n            break;\n\n          case 'error': {\n            const errorMessage =\n              data.payload.message_text || 'Erro desconhecido';\n            setError(new Error(errorMessage));\n            onError?.(new Error(errorMessage));\n            break;\n          }\n        }\n      } catch (err) {\n        console.error('Error parsing WebSocket message:', err);\n      }\n    },\n    [onError]\n  );\n\n  /**\n   * Connect to WebSocket\n   */\n  const connect = useCallback(() => {\n    // Prevent multiple simultaneous connection attempts\n    if (isConnectingRef.current) {\n      return;\n    }\n\n    // Build WebSocket URL with query params\n    const url = new URL(wsUrl);\n    url.searchParams.set('roomId', roomId);\n    url.searchParams.set('token', token);\n\n    // Close existing connection\n    if (wsRef.current) {\n      wsRef.current.close();\n    }\n\n    // Create new WebSocket connection\n    isConnectingRef.current = true;\n    const ws = new WebSocket(url.toString());\n    wsRef.current = ws;\n\n    ws.onopen = () => {\n      isConnectingRef.current = false;\n      setIsConnected(true);\n      setError(null);\n      reconnectAttemptsRef.current = 0;\n      ws.send(JSON.stringify({ type: 'getInitialData' }));\n\n      onConnect?.();\n    };\n\n    ws.onmessage = handleMessage;\n\n    ws.onerror = () => {\n      isConnectingRef.current = false;\n      const error = new Error('Erro na conexão WebSocket');\n      setError(error);\n      onError?.(error);\n    };\n\n    ws.onclose = (event) => {\n      isConnectingRef.current = false;\n      setIsConnected(false);\n      onDisconnect?.();\n\n      // Auto-reconnect if not manual disconnect and within attempts limit\n      if (\n        autoReconnect &&\n        !isManualDisconnectRef.current &&\n        reconnectAttemptsRef.current < maxReconnectAttempts &&\n        event.code !== 4001 && // Unauthorized\n        event.code !== 4002 && // Missing roomId\n        event.code !== 4003 // Access denied\n      ) {\n        reconnectAttemptsRef.current += 1;\n        reconnectTimeoutRef.current = setTimeout(() => {\n          connect();\n        }, reconnectInterval);\n      }\n    };\n  }, [\n    wsUrl,\n    roomId,\n    token,\n    handleMessage,\n    onConnect,\n    onDisconnect,\n    onError,\n    autoReconnect,\n    reconnectInterval,\n    maxReconnectAttempts,\n  ]);\n\n  // Keep connect ref updated\n  connectRef.current = connect;\n\n  /**\n   * Reconnect to WebSocket\n   */\n  const reconnect = useCallback(() => {\n    isManualDisconnectRef.current = false;\n    reconnectAttemptsRef.current = 0;\n    connectRef.current();\n  }, []);\n\n  // Connect on mount, disconnect on unmount\n  // Only connect when roomId is provided\n  useEffect(() => {\n    if (!roomId) {\n      return;\n    }\n\n    // Clear any pending reconnect\n    if (reconnectTimeoutRef.current) {\n      clearTimeout(reconnectTimeoutRef.current);\n      reconnectTimeoutRef.current = null;\n    }\n\n    isManualDisconnectRef.current = false;\n    isConnectingRef.current = false;\n    reconnectAttemptsRef.current = 0;\n\n    // Close existing connection before opening new one\n    if (wsRef.current) {\n      wsRef.current.close(1000, 'Room changed');\n      wsRef.current = null;\n    }\n\n    // Small delay to ensure previous connection is closed\n    const timeoutId = setTimeout(() => {\n      connectRef.current();\n    }, 100);\n\n    return () => {\n      clearTimeout(timeoutId);\n      isManualDisconnectRef.current = true;\n      isConnectingRef.current = false;\n      if (reconnectTimeoutRef.current) {\n        clearTimeout(reconnectTimeoutRef.current);\n      }\n      wsRef.current?.close(1000, 'Component unmounted');\n    };\n  }, [roomId]);\n\n  return {\n    isConnected,\n    messages,\n    participants,\n    sendMessage,\n    leave,\n    error,\n    reconnect,\n    currentUserId: userId,\n  };\n}\n\n/**\n * Factory function to create a pre-configured useChat hook\n *\n * @param baseWsUrl - Base WebSocket URL\n * @returns Factory function that creates the hook with room-specific options\n *\n * @example\n * ```tsx\n * // In your app setup\n * const createChatHook = createUseChat('wss://api.example.com/chat/ws');\n *\n * // In component\n * const { messages, sendMessage } = createChatHook({\n *   token: authToken,\n *   roomId: 'room-123',\n *   userId: 'user-456',\n * });\n * ```\n */\nexport function createUseChat(baseWsUrl: string) {\n  return (options: Omit<UseChatOptions, 'wsUrl'>) =>\n    useChat({ ...options, wsUrl: baseWsUrl });\n}\n","import { useState, useCallback } from 'react';\nimport type {\n  ChatApiClient,\n  ChatRoom,\n  ChatRoomWithDetails,\n  ChatUser,\n  AvailableUsersResponse,\n  CreateRoomResponse,\n  GetRoomsResponse,\n} from '../types/chat';\n\n/**\n * Options for the useChatRooms hook\n */\nexport interface UseChatRoomsOptions {\n  apiClient: ChatApiClient;\n}\n\n/**\n * Return type for the useChatRooms hook\n */\nexport interface UseChatRoomsReturn {\n  /** List of user's chat rooms */\n  rooms: ChatRoomWithDetails[];\n  /** Available users for creating new chat rooms */\n  availableUsers: ChatUser[];\n  /** Loading state */\n  loading: boolean;\n  /** Error state */\n  error: Error | null;\n  /** Fetch user's chat rooms */\n  fetchRooms: () => Promise<void>;\n  /** Fetch available users for chat */\n  fetchAvailableUsers: () => Promise<void>;\n  /** Create a new chat room */\n  createRoom: (participantIds: string[]) => Promise<ChatRoom | null>;\n  /** Clear error state */\n  clearError: () => void;\n}\n\n/**\n * Hook for managing chat rooms via REST API\n *\n * Provides functionality to:\n * - List user's chat rooms\n * - Fetch available users for new chats\n * - Create new chat rooms\n *\n * @param options - Hook configuration options\n * @returns Chat rooms state and actions\n *\n * @example\n * ```tsx\n * const { rooms, fetchRooms, createRoom } = useChatRooms({ apiClient: api });\n *\n * useEffect(() => {\n *   fetchRooms();\n * }, []);\n *\n * const handleCreateRoom = async (userIds: string[]) => {\n *   const room = await createRoom(userIds);\n *   if (room) {\n *     // Navigate to the new room\n *   }\n * };\n * ```\n */\nexport function useChatRooms({\n  apiClient,\n}: UseChatRoomsOptions): UseChatRoomsReturn {\n  const [rooms, setRooms] = useState<ChatRoomWithDetails[]>([]);\n  const [availableUsers, setAvailableUsers] = useState<ChatUser[]>([]);\n  const [loading, setLoading] = useState(false);\n  const [error, setError] = useState<Error | null>(null);\n\n  /**\n   * Fetch user's chat rooms\n   */\n  const fetchRooms = useCallback(async () => {\n    setLoading(true);\n    setError(null);\n\n    try {\n      const response = await apiClient.get<{ data: GetRoomsResponse }>(\n        '/chat/rooms'\n      );\n      setRooms(response.data.data.rooms);\n    } catch (err) {\n      const error =\n        err instanceof Error ? err : new Error('Erro ao carregar salas');\n      setError(error);\n      console.error('Error fetching chat rooms:', err);\n    } finally {\n      setLoading(false);\n    }\n  }, [apiClient]);\n\n  /**\n   * Fetch available users for chat\n   */\n  const fetchAvailableUsers = useCallback(async () => {\n    setLoading(true);\n    setError(null);\n\n    try {\n      const response = await apiClient.get<{ data: AvailableUsersResponse }>(\n        '/chat/available-users'\n      );\n      setAvailableUsers(response.data.data.users);\n    } catch (err) {\n      const error =\n        err instanceof Error ? err : new Error('Erro ao carregar usuários');\n      setError(error);\n      console.error('Error fetching available users:', err);\n    } finally {\n      setLoading(false);\n    }\n  }, [apiClient]);\n\n  /**\n   * Create a new chat room\n   */\n  const createRoom = useCallback(\n    async (participantIds: string[]): Promise<ChatRoom | null> => {\n      setLoading(true);\n      setError(null);\n\n      try {\n        const response = await apiClient.post<{ data: CreateRoomResponse }>(\n          '/chat/rooms',\n          {\n            participantIds,\n          }\n        );\n\n        // Refresh rooms list after creating\n        await fetchRooms();\n\n        return response.data.data.room;\n      } catch (err) {\n        const error =\n          err instanceof Error ? err : new Error('Erro ao criar sala');\n        setError(error);\n        console.error('Error creating chat room:', err);\n        return null;\n      } finally {\n        setLoading(false);\n      }\n    },\n    [apiClient, fetchRooms]\n  );\n\n  /**\n   * Clear error state\n   */\n  const clearError = useCallback(() => {\n    setError(null);\n  }, []);\n\n  return {\n    rooms,\n    availableUsers,\n    loading,\n    error,\n    fetchRooms,\n    fetchAvailableUsers,\n    createRoom,\n    clearError,\n  };\n}\n\n/**\n * Factory function to create a pre-configured useChatRooms hook\n *\n * @param apiClient - API client instance\n * @returns Pre-configured hook function\n *\n * @example\n * ```tsx\n * // In your app setup\n * import { createUseChatRooms } from 'analytica-frontend-lib';\n * import api from './services/api';\n *\n * export const useChatRooms = createUseChatRooms(api);\n *\n * // Then use directly in components\n * const { rooms, fetchRooms } = useChatRooms();\n * ```\n */\nexport function createUseChatRooms(apiClient: ChatApiClient) {\n  return () => useChatRooms({ apiClient });\n}\n"],"mappings":"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","names":["useState","useEffect","useCallback","useRef","error","useState","useCallback","error","useState","useRef","useEffect","useCallback"]}