import {
  SUPPORT_CHAT_WS_EVENTS,
  SUPPORT_CHAT_WS_NAMESPACE,
  type SupportConversationDto,
  type SupportMessageEvent,
} from "@edr/types";
import { useQueryClient } from "@tanstack/react-query";
import { useEffect, useRef } from "react";
import { io } from "socket.io-client";

import { AUTH_TOKEN_COOKIE, getCookie } from "@/auth/cookies";
import { API_BASE_URL } from "@/constants/apiConfig";

import {
  appendMessageToCache,
  SUPPORT_CONVERSATIONS_KEY,
  SUPPORT_UNREAD_KEY,
  supportMessagesKey,
} from "./useSupport";

// The socket namespace lives at the server root, not under the `/api` REST
// prefix — strip a trailing `/api` if the base URL carries one.
const SOCKET_ORIGIN = String(API_BASE_URL ?? "").replace(/\/api\/?$/, "");

/**
 * Subscribes the signed-in agent to live support-chat pushes for the whole
 * shared inbox. Any new message or conversation change refreshes the affected
 * thread, the inbox list, and the unread badge; `onMessage` fires for toasts.
 */
export function useSupportSocket(
  enabled: boolean,
  onMessage?: (event: SupportMessageEvent) => void,
) {
  const qc = useQueryClient();
  const onMessageRef = useRef(onMessage);
  onMessageRef.current = onMessage;

  useEffect(() => {
    if (!enabled) return;
    const token = getCookie(AUTH_TOKEN_COOKIE);
    if (!token) return;

    const socket = io(`${SOCKET_ORIGIN}/${SUPPORT_CHAT_WS_NAMESPACE}`, {
      auth: { token },
      transports: ["websocket"],
      withCredentials: true,
    });

    socket.on(
      SUPPORT_CHAT_WS_EVENTS.MESSAGE_NEW,
      (event: SupportMessageEvent) => {
        // Append rather than invalidate: the thread is paginated, and invalidating
        // it would refetch every page the agent has scrolled back through on every
        // single inbound message.
        if (appendMessageToCache(qc, event.message) === "uncached") {
          // The thread's first page is still loading and may have been read before
          // this message existed — without this it would go missing until some
          // unrelated refetch. Cheap: there are no pages to re-fetch yet.
          qc.invalidateQueries({
            queryKey: supportMessagesKey(event.message.conversationId),
          });
        }
        qc.invalidateQueries({ queryKey: SUPPORT_CONVERSATIONS_KEY });
        qc.invalidateQueries({ queryKey: SUPPORT_UNREAD_KEY });
        onMessageRef.current?.(event);
      },
    );

    socket.on(
      SUPPORT_CHAT_WS_EVENTS.CONVERSATION_UPDATED,
      (_conversation: SupportConversationDto) => {
        qc.invalidateQueries({ queryKey: SUPPORT_CONVERSATIONS_KEY });
        qc.invalidateQueries({ queryKey: SUPPORT_UNREAD_KEY });
      },
    );

    return () => {
      socket.off();
      socket.disconnect();
    };
  }, [enabled, qc]);
}
