import { useState, useEffect, useRef } from "react";

type UseSSETabResult = {
  isActiveSSETab: boolean;
  updateSSEValue: <T>(value: T) => void;
};

export const useSSETab = <T = unknown>(
  sseName: string,
  onUpdateValue?: (value: T) => void
): UseSSETabResult => {
  const [openTimeSetted, seteOpenTimeSetted] = useState<boolean>(false);
  const [activeSSETab, setActiveSSETab] = useState<boolean>(false);
  const updateTimeIntervalId = useRef<NodeJS.Timer | null>(null);
  const checkConnectionIntervalId = useRef<NodeJS.Timer | null>(null);

  useEffect(() => {
    setOpenTime();
    checkConnectionIntervalId.current = setInterval(checkConnection, 5000);

    const onUpdate = (event: StorageEvent) => {
      if (event.key === `sse-${sseName}-update` && event.newValue) {
        onUpdateValue?.(JSON.parse(event.newValue));
      }
    };

    window.addEventListener("storage", onUpdate);

    return () => {
      if (checkConnectionIntervalId.current) {
        clearInterval(checkConnectionIntervalId.current);
      }

      window.removeEventListener("storage", onUpdate);
    };
  }, []);

  useEffect(() => {
    if (activeSSETab) {
      if (updateTimeIntervalId.current) {
        clearInterval(updateTimeIntervalId.current);
      }

      updateTime();
      updateTimeIntervalId.current = setInterval(updateTime, 5000);

      return () => {
        setActiveSSETab(false);

        if (updateTimeIntervalId.current) {
          clearInterval(updateTimeIntervalId.current);
        }
      };
    }
  }, [activeSSETab]);

  const updateTime = () => {
    const time = new Date().getTime();

    localStorage.setItem(`sse-${sseName}`, String(time));
  };

  const checkConnection = (): boolean => {
    const time = new Date().getTime();
    const lastMessageTime = Number(localStorage.getItem(`sse-${sseName}`));

    if (time - lastMessageTime > 5000) {
      setActiveSSETab(true);

      return false;
    }

    return true;
  };

  const setOpenTime = () => {
    if (openTimeSetted) {
      return;
    }

    if (!checkConnection()) {
      setActiveSSETab(true);
    }

    seteOpenTimeSetted(true);
  };

  const updateSSEValue = <T>(value: T) => {
    localStorage.setItem(`sse-${sseName}-update`, JSON.stringify(value));
  };

  return { isActiveSSETab: activeSSETab, updateSSEValue };
};
