import { useEffect } from "react";
import { useQueryClient } from "@tanstack/react-query";
import { supabase } from "../lib/supabase";
import type { RealtimeChannel } from "@supabase/supabase-js";
import type { CommunityPost } from "../stores/community";

/**
 * Realtime-Subscription für die Community-Feed-Page.
 * Lauscht auf:
 *  - INSERT auf community_posts → invalidiert die Feed-Query (frischer Refetch)
 *  - UPDATE auf community_posts → patcht likes/comments-Counts inline
 *  - UPDATE auf domain_submissions → patcht domain_vote-Posts mit neuem Status
 *  - UPDATE auf game_challenges → patcht challenge-Status
 *
 * Pendant zum Nuxt-`communityStore.startRealtime()` aus apps/rebreak/.
 */
export function useCommunityRealtime(enabled: boolean = true) {
  const queryClient = useQueryClient();

  useEffect(() => {
    if (!enabled) return;
    let channel: RealtimeChannel | null = null;
    let cancelled = false;
    let reconnectTimer: ReturnType<typeof setTimeout> | null = null;

    async function subscribe() {
      const { data } = await supabase.auth.getSession();
      const session = data.session;
      if (!session?.access_token) return;
      if (cancelled) return;

      const myId = session.user.id;

      channel = supabase
        .channel(`community:posts:${Date.now()}`)
        .on(
          "postgres_changes",
          { event: "INSERT", schema: "rebreak", table: "community_posts" },
          (payload: any) => {
            const r = payload.new;
            if (r.user_id === myId) return; // eigene Posts schon optimistisch hinzugefügt
            if (r.is_moderated) return;
            // Einfacher als Detail-Fetch: alle Feed-Queries invalidieren
            queryClient.invalidateQueries({ queryKey: ["community-posts"] });
          },
        )
        .on(
          "postgres_changes",
          { event: "UPDATE", schema: "rebreak", table: "community_posts" },
          (payload: any) => {
            const r = payload.new;
            patchPostInAllQueries(queryClient, r.id, (p) => ({
              ...p,
              likesCount: r.likes_count ?? p.likesCount,
              dislikesCount: r.dislikes_count ?? p.dislikesCount,
              commentsCount: r.comments_count ?? p.commentsCount,
              repostsCount: r.reposts_count ?? p.repostsCount,
            }));
          },
        )
        .on(
          "postgres_changes",
          { event: "UPDATE", schema: "rebreak", table: "domain_submissions" },
          (payload: any) => {
            const r = payload.new;
            if (
              r.status !== "approved" &&
              r.status !== "rejected" &&
              r.status !== "in_review"
            ) {
              return;
            }
            patchPostInAllQueries(queryClient, null, (p) => {
              if (p.submission?.domain == null) return p;
              // Wir kennen die submissionId nicht direkt am Post, also matche per domain.
              // Realistisch unique pro user_id, aber Feed enthält Post mit submission-Objekt.
              // Wenn der Post diese submission referenziert, patchen.
              if (!p.submission || (p as any).submissionId !== r.id) {
                // Falls du submissionId an Post-Schema hängst, hier nutzen.
                // Solange nicht: invalidate fallback unten.
                return p;
              }
              return {
                ...p,
                submission: {
                  ...p.submission,
                  status: r.status,
                  yesVotes: r.yes_votes ?? p.submission.yesVotes,
                  noVotes: r.no_votes ?? p.submission.noVotes,
                  reviewedAt: r.reviewed_at ?? p.submission.reviewedAt,
                },
              };
            });
            // Sicherheitshalber auch invalidieren — domain_vote ist selten genug.
            queryClient.invalidateQueries({ queryKey: ["community-posts"] });
          },
        )
        .on(
          "postgres_changes",
          { event: "UPDATE", schema: "rebreak", table: "game_challenges" },
          (payload: any) => {
            const r = payload.new;
            patchPostInAllQueries(queryClient, null, (p) =>
              p.challengeId === r.id ? { ...p, challengeStatus: r.status } : p,
            );
          },
        )
        .subscribe((status) => {
          if (status === "CHANNEL_ERROR" || status === "TIMED_OUT") {
            cleanup();
            if (reconnectTimer) clearTimeout(reconnectTimer);
            reconnectTimer = setTimeout(() => {
              if (!cancelled) subscribe();
            }, 3000);
          }
        });
    }

    function cleanup() {
      if (channel) {
        supabase.removeChannel(channel);
        channel = null;
      }
    }

    subscribe();

    return () => {
      cancelled = true;
      if (reconnectTimer) clearTimeout(reconnectTimer);
      cleanup();
    };
  }, [enabled, queryClient]);
}

function patchPostInAllQueries(
  queryClient: ReturnType<typeof useQueryClient>,
  postId: string | null,
  patcher: (p: CommunityPost) => CommunityPost,
) {
  const queries = queryClient.getQueriesData<CommunityPost[]>({
    queryKey: ["community-posts"],
  });
  for (const [key, data] of queries) {
    if (!Array.isArray(data)) continue;
    const next = data.map((p) => {
      if (postId !== null && p.id !== postId) return p;
      return patcher(p);
    });
    queryClient.setQueryData(key, next);
  }
}
