"use client";

import {
  createContext,
  ReactNode,
  useCallback,
  useContext,
  useEffect,
  useRef,
  useState,
} from "react";
import {
  AdminOrder,
  fetchAllOrders,
  updateOrderStatus,
  deleteOrder,
} from "./orders";

// Polling, not a WebSocket/Realtime subscription — Supabase's
// postgres_changes had no MySQL equivalent to rebuild without a
// WebSocket server, which shared hosting can't run (same reasoning as
// the User Panel's notifications — see sharednet-ui's
// NOTIFICATION_POLL_MS). 20s here rather than the User Panel's 30s,
// since a new order/payment showing up promptly matters more to an
// admin actively working the queue than a notification badge does to
// a browsing customer.
const ORDERS_POLL_MS = 20_000;

interface AdminOrdersContextValue {
  orders: AdminOrder[];
  loading: boolean;
  error: string | null;
  newOrderPulse: number;
  refetch: () => Promise<void>;
  approveOrder: (order: AdminOrder) => Promise<void>;
  rejectOrder: (order: AdminOrder, notes?: string) => Promise<void>;
  completeOrder: (order: AdminOrder) => Promise<void>;
  removeOrder: (order: AdminOrder) => Promise<void>;
}

const AdminOrdersContext = createContext<AdminOrdersContextValue | null>(null);

export function AdminOrdersProvider({ children }: { children: ReactNode }) {
  const [orders, setOrders] = useState<AdminOrder[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [newOrderPulse, setNewOrderPulse] = useState(0);
  const hasLoadedOnce = useRef(false);
  const knownOrderIds = useRef<Set<string>>(new Set());

  const refetch = useCallback(async () => {
    try {
      const result = await fetchAllOrders();
      // A pulse fires when a genuinely new order id shows up that
      // wasn't there on the previous fetch — replaces what the
      // Realtime subscription's INSERT event used to trigger.
      if (hasLoadedOnce.current) {
        const hasNew = result.some((o) => !knownOrderIds.current.has(o.dbId));
        if (hasNew) setNewOrderPulse((n) => n + 1);
      }
      knownOrderIds.current = new Set(result.map((o) => o.dbId));
      setOrders(result);
      setError(null);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Couldn't load orders.");
    } finally {
      setLoading(false);
      hasLoadedOnce.current = true;
    }
  }, []);

  useEffect(() => {
    refetch();
    const interval = setInterval(refetch, ORDERS_POLL_MS);
    window.addEventListener("focus", refetch);
    return () => {
      clearInterval(interval);
      window.removeEventListener("focus", refetch);
    };
  }, [refetch]);

  const value: AdminOrdersContextValue = {
    orders,
    loading,
    error,
    newOrderPulse,
    refetch,
    approveOrder: async (order) => {
      await updateOrderStatus(order.dbId, "approved");
      await refetch();
    },
    rejectOrder: async (order, notes) => {
      await updateOrderStatus(order.dbId, "rejected", notes);
      await refetch();
    },
    completeOrder: async (order) => {
      await updateOrderStatus(order.dbId, "completed");
      await refetch();
    },
    removeOrder: async (order) => {
      await deleteOrder(order.dbId, order.status);
      await refetch();
    },
  };

  return (
    <AdminOrdersContext.Provider value={value}>{children}</AdminOrdersContext.Provider>
  );
}

export function useAdminOrders() {
  const ctx = useContext(AdminOrdersContext);
  if (!ctx) throw new Error("useAdminOrders must be used within AdminOrdersProvider");
  return ctx;
}
