import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from "react";

import { getUserSessions } from "../api/sessions";
import type { Session } from "../api/sessions";

export interface SessionsContextType {
  sessions: Session[];
  isLoading: boolean;
  error: Error | null;
  refreshSessions: () => Promise<void>;
  addOrUpdateSession: (session: Session) => void;
  removeSession: (id: string) => void;
}

const SessionsContext = createContext<SessionsContextType | undefined>(undefined);

export const SessionsProvider = ({ children }: { children: ReactNode }) => {
  const [sessions, setSessions] = useState<Session[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<Error | null>(null);

  const refreshSessions = useCallback(async () => {
    setIsLoading(true);
    setError(null);
    try {
      const data = await getUserSessions();
      setSessions(data);
    } catch (err) {
      setError(err instanceof Error ? err : new Error("Failed to load sessions"));
    } finally {
      setIsLoading(false);
    }
  }, []);

  const addOrUpdateSession = useCallback((session: Session) => {
    setSessions((prev) => {
      const existing = prev.find((s) => s.id === session.id);
      if (existing) {
        return prev.map((s) => (s.id === session.id ? { ...s, ...session } : s));
      }
      return [session, ...prev];
    });
  }, []);

  const removeSession = useCallback((id: string) => {
    setSessions((prev) => prev.filter((s) => s.id !== id));
  }, []);

  useEffect(() => {
    void refreshSessions();
    // Poll every 30 seconds to reconcile shared state with the server.
    const interval = setInterval(() => {
      void refreshSessions();
    }, 30000);
    return () => clearInterval(interval);
  }, [refreshSessions]);

  const value = useMemo(
    () => ({
      sessions,
      isLoading,
      error,
      refreshSessions,
      addOrUpdateSession,
      removeSession,
    }),
    [sessions, isLoading, error, refreshSessions, addOrUpdateSession, removeSession],
  );

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

export const useSessions = () => {
  const context = useContext(SessionsContext);
  if (context === undefined) {
    throw new Error("useSessions must be used within a SessionsProvider");
  }
  return context;
};
