"use client";

import { useEffect, useRef } from "react";
import { useQueryClient } from "@tanstack/react-query";
import { resolveBaseUrl, queryKeys } from "@/core/api";
import { logger } from "@/core/logger";
import { useAuthSession } from "@/features/auth/stores/auth.store";

type RealtimeEventEnvelope<TEvent extends string = string, TData = unknown> = {
  event: TEvent;
  data: TData;
};

export function AccountEventsListener() {
  const { isAuthenticated } = useAuthSession();
  const queryClient = useQueryClient();

  const clientRef = useRef<{ close: () => void } | null>(null);

  useEffect(() => {
    if (!isAuthenticated) {
      clientRef.current?.close();
      clientRef.current = null;
      return;
    }

    let cancelled = false;
    let es: EventSource | null = null;
    let reconnectTimeout: ReturnType<typeof setTimeout> | null = null;

    const baseUrl = resolveBaseUrl();
    const url = new URL("/api/events", baseUrl).toString();

    const connect = () => {
      if (cancelled) return;

      logger.debug("Connecting to account events stream", { url });
      es = new EventSource(url, { withCredentials: true });

      const onMessage = (event: MessageEvent<string>) => {
        try {
          const parsed = JSON.parse(event.data) as RealtimeEventEnvelope;
          if (!parsed || typeof parsed !== "object") return;

          if (parsed.event === "services.eligibility.changed") {
            logger.info("Received services.eligibility.changed; invalidating services queries");
            void queryClient.invalidateQueries({ queryKey: queryKeys.services.all() });
            return;
          }

          if (parsed.event === "services.changed") {
            logger.info("Received services.changed; invalidating services queries");
            void queryClient.invalidateQueries({ queryKey: queryKeys.services.all() });
            return;
          }

          if (parsed.event === "orders.changed") {
            logger.info("Received orders.changed; invalidating orders + dashboard queries");
            void queryClient.invalidateQueries({ queryKey: queryKeys.orders.list() });
            // Dashboard summary often depends on orders/subscriptions; cheap to keep in sync.
            void queryClient.invalidateQueries({ queryKey: queryKeys.dashboard.summary() });
            void queryClient.invalidateQueries({ queryKey: queryKeys.me.status() });
            return;
          }
        } catch (error) {
          logger.warn("Failed to parse account event", { error });
        }
      };

      const onError = (error: Event) => {
        logger.warn("Account events stream disconnected", { error });
        es?.close();
        es = null;

        if (!cancelled) {
          reconnectTimeout = setTimeout(connect, 5000);
        }
      };

      es.addEventListener("message", onMessage as EventListener);
      es.onerror = onError;
    };

    connect();

    clientRef.current = {
      close: () => {
        cancelled = true;
        if (es) es.close();
        if (reconnectTimeout) clearTimeout(reconnectTimeout);
      },
    };

    return () => {
      clientRef.current?.close();
      clientRef.current = null;
    };
  }, [isAuthenticated, queryClient]);

  return null;
}
