import { WebSocket } from "partysocket";
import * as React from "react";

export type BrevitySocketOptions = {
  maxReconnectionDelay?: number;
  minReconnectionDelay?: number;
  reconnectionDelayGrowFactor?: number;
  minUptime?: number;
  connectionTimeout?: number;
  maxRetries?: number;
  maxEnqueuedMessages?: number;
  startClosed?: boolean;
  debug?: boolean;
};

type UseBrevitySocketOptions = BrevitySocketOptions & {
  appId: string;
  host?: string;
  tags?: string[];
  onMessage: (event: WebSocketEventMap["message"]) => void;
};

// A React hook that wraps PartySocket
export function useBrevitySocket(options: UseBrevitySocketOptions) {
  const [tags, setTags] = React.useState<string[]>(options.tags ?? []);
  const {
    onMessage,
    host = "realtime.devize.com",
    appId,
    ...brevitySocketOptions
  } = options;
  React.useEffect(() => {
    if (Array.isArray(options.tags) && options.tags.length) {
      setTags((previousTags) => {
        const unique = new Set([...previousTags, ...options.tags!]);
        return Array.from(unique).sort();
      });
    }
  }, [options.tags?.join(",")]);
  React.useEffect(() => {
    document.addEventListener("REGISTER_TAGS", (c: CustomEvent) => {
      const tags = c.detail;
      if (Array.isArray(tags) && tags.length) {
        setTags((previousTags) => {
          const unique = new Set([...previousTags, ...tags]);
          return Array.from(unique).sort();
        });
      }
    });
  }, []);
  React.useEffect(() => {
    if (!tags || !tags?.length) {
      return;
    }
    const params = new URLSearchParams();
    tags.forEach((tag) => params.append("tags", tag));
    const ws = new WebSocket(
      `wss://${host}/api/v1/subscribe/${appId}?${params}`,
      undefined,
      brevitySocketOptions,
    );
    const handleMessage = (e: MessageEvent) => {
      const data = JSON.parse(e.data);
      onMessage(data);
      document.dispatchEvent(new CustomEvent("REALTIME", { detail: data }));
    };
    ws.addEventListener("message", handleMessage);
    return () => {
      ws.removeEventListener("message", handleMessage);
      ws.close();
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [appId, tags?.join(",")]);
}
