import { create } from "zustand";
import { apiFetch } from "../lib/api";
import { supabase } from "../lib/supabase";
import type { RealtimeChannel } from "@supabase/supabase-js";

export interface AppNotification {
  id: string;
  type: string;
  actorName: string;
  actorAvatar: string | null;
  postId: string | null;
  preview: string | null;
  readAt: string | null;
  createdAt: string;
}

type NotificationState = {
  items: AppNotification[];
  unread: number;
  loaded: boolean;
  load: () => Promise<void>;
  markRead: () => Promise<void>;
  remove: (id: string) => Promise<void>;
  startRealtime: () => Promise<void>;
  stopRealtime: () => void;
  reset: () => void;
};

let realtimeSub: RealtimeChannel | null = null;
let reconnectTimer: ReturnType<typeof setTimeout> | null = null;

export const useNotificationStore = create<NotificationState>((set, get) => ({
  items: [],
  unread: 0,
  loaded: false,

  load: async () => {
    try {
      const res = await apiFetch<{ items: AppNotification[]; unread: number }>(
        "/api/notifications",
      );
      set({ items: res.items ?? [], unread: res.unread ?? 0, loaded: true });
    } catch (err) {
      console.warn("[notifications] load failed:", err);
    }
  },

  markRead: async () => {
    if (get().unread === 0) return;
    const now = new Date().toISOString();
    set((s) => ({
      unread: 0,
      items: s.items.map((n) => ({ ...n, readAt: n.readAt ?? now })),
    }));
    try {
      await apiFetch("/api/notifications/read", { method: "POST" });
    } catch (err) {
      console.warn("[notifications] markRead failed:", err);
    }
  },

  remove: async (id) => {
    set((s) => ({ items: s.items.filter((n) => n.id !== id) }));
    try {
      await apiFetch(`/api/notifications/${id}`, { method: "DELETE" });
    } catch (err) {
      console.warn("[notifications] remove failed:", err);
    }
  },

  startRealtime: async () => {
    if (realtimeSub) return;
    const { data } = await supabase.auth.getSession();
    const session = data.session;
    if (!session?.user?.id) return;

    const myId = session.user.id;

    realtimeSub = supabase
      .channel(`notifications:${myId}:${Date.now()}`)
      .on(
        "postgres_changes",
        {
          event: "INSERT",
          schema: "rebreak",
          table: "notifications",
          filter: `recipient_id=eq.${myId}`,
        },
        (payload: any) => {
          const r = payload.new;
          const notif: AppNotification = {
            id: r.id,
            type: r.type,
            actorName: r.actor_name,
            actorAvatar: r.actor_avatar ?? null,
            postId: r.post_id ?? null,
            preview: r.preview ?? null,
            readAt: null,
            createdAt: r.created_at,
          };
          set((s) => {
            if (s.items.find((n) => n.id === notif.id)) return s;
            return { items: [notif, ...s.items], unread: s.unread + 1 };
          });
        },
      )
      .on(
        "postgres_changes",
        {
          event: "DELETE",
          schema: "rebreak",
          table: "notifications",
          filter: `recipient_id=eq.${myId}`,
        },
        (payload: any) => {
          const id = payload.old?.id;
          if (!id) return;
          set((s) => ({ items: s.items.filter((n) => n.id !== id) }));
        },
      )
      .subscribe((status) => {
        if (status === "CHANNEL_ERROR" || status === "TIMED_OUT") {
          console.warn("[notifRealtime] error:", status);
          get().stopRealtime();
          if (reconnectTimer) clearTimeout(reconnectTimer);
          reconnectTimer = setTimeout(() => {
            get().startRealtime();
          }, 3000);
        }
      });
  },

  stopRealtime: () => {
    if (realtimeSub) {
      supabase.removeChannel(realtimeSub);
      realtimeSub = null;
    }
    if (reconnectTimer) {
      clearTimeout(reconnectTimer);
      reconnectTimer = null;
    }
  },

  reset: () => {
    get().stopRealtime();
    set({ items: [], unread: 0, loaded: false });
  },
}));
