'use client';

import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useRef,
  useState,
  type ReactNode,
} from 'react';
import { subscribeBroadcast } from '@/lib/queue/broadcast';
import { runSync } from '@/lib/queue/sync';
import { db } from '@/lib/queue/db';

interface SyncState {
  pendingCount: number;
  deadLetterCount: number;
}

const SyncCtx = createContext<SyncState>({ pendingCount: 0, deadLetterCount: 0 });
export const useSyncState = () => useContext(SyncCtx);

export function SyncProvider({ children }: { children: ReactNode }) {
  const [state, setState] = useState<SyncState>({ pendingCount: 0, deadLetterCount: 0 });
  const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);

  const refreshCounts = useCallback(async () => {
    const [p, d] = await Promise.all([db.pending.count(), db.deadLetters.count()]);
    setState({ pendingCount: p, deadLetterCount: d });
  }, []);

  const sync = useCallback(async () => {
    await runSync();
    await refreshCounts();
  }, [refreshCounts]);

  useEffect(() => {
    refreshCounts();

    const unsub = subscribeBroadcast(async () => refreshCounts());

    const onOnline = () => sync();
    const onVisible = () => {
      if (document.visibilityState === 'visible' && navigator.onLine) sync();
    };

    window.addEventListener('online', onOnline);
    document.addEventListener('visibilitychange', onVisible);

    // Poll every 10s as a fallback
    timerRef.current = setInterval(() => {
      if (navigator.onLine) sync();
    }, 10_000);

    // Register Background Sync if SW + API available
    if ('serviceWorker' in navigator && 'SyncManager' in window) {
      navigator.serviceWorker.ready
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        .then((reg) => (reg as any).sync.register('mai-call-sync'))
        .catch(() => {/* not supported or permission denied */});
    }

    // Initial sync attempt
    if (navigator.onLine) sync();

    return () => {
      unsub();
      window.removeEventListener('online', onOnline);
      document.removeEventListener('visibilitychange', onVisible);
      if (timerRef.current) clearInterval(timerRef.current);
    };
  }, [sync, refreshCounts]);

  return <SyncCtx.Provider value={state}>{children}</SyncCtx.Provider>;
}
