"use client";

import useSWR from "swr";
import { useEffect, useRef } from "react";
import { fetcher, FetchError } from "@/lib/fetcher";
import { RoomStatus } from "@/types";

// Exponential backoff with jitter: min(2000 * 2^attempt + rand(500), 60s)
function backoffMs(attempt: number): number {
  return Math.min(2000 * Math.pow(2, attempt) + Math.random() * 500, 60_000);
}

export function useRoomPolling(
  roomId: string | undefined,
  userId?: string,
) {
  const { data, error, isLoading, mutate } = useSWR<RoomStatus>(
    roomId ? `/api/room/${roomId}` : null,
    fetcher,
    {
      revalidateOnFocus: true,
      shouldRetryOnError: (err) => {
        if (err instanceof FetchError && (err.status === 401 || err.status === 404)) return false;
        return err?.message !== "NOT_FOUND";
      },
    },
  );

  const fallbackRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const attemptRef = useRef(0);
  const notFound = error?.message === "NOT_FOUND";

  useEffect(() => {
    if (!roomId || !userId) return;
    const es = new EventSource(
      `/api/room/${roomId}/events?userId=${encodeURIComponent(userId)}`,
    );

    const clearFallback = () => {
      if (fallbackRef.current) {
        clearTimeout(fallbackRef.current);
        fallbackRef.current = null;
      }
    };

    es.onmessage = (e) => {
      try {
        const parsed = JSON.parse(e.data);
        if (parsed.roomId) {
          mutate(parsed, { revalidate: false });
        }
      } catch (e) {
        console.error("useRoomPolling: malformed SSE message:", e);
      }
    };

    es.onerror = () => {
      if (!fallbackRef.current) {
        const delay = backoffMs(attemptRef.current++);
        fallbackRef.current = setTimeout(() => {
          mutate();
          fallbackRef.current = null;
        }, delay);
      }
    };

    es.onopen = () => {
      attemptRef.current = 0;
      clearFallback();
    };

    return () => {
      es.close();
      clearFallback();
    };
  }, [roomId, userId, mutate]);

  return {
    userCount: data?.userCount ?? 0,
    match: data?.match ?? null,
    matchType: data?.matchType ?? null,
    matchLikes: data?.matchLikes ?? 0,
    runnerUps: data?.runnerUps ?? [],
    likeCounts: data?.likeCounts ?? {},
    swipeCounts: data?.swipeCounts ?? {},
    restaurants: data?.restaurants ?? [],
    creatorId: data?.creatorId ?? "",
    locked: data?.locked ?? false,
    users: data?.users ?? [],
    userProfiles: data?.userProfiles ?? {},
    scene: data?.scene ?? "eat" as const,
    notFound,
    isLoading,
    error,
    mutate,
  };
}
