import { useEffect, useState, useCallback, type ReactNode } from "react";
import { AuthContext, type AuthContextValue, type AuthStatus } from "./useAuth";
import { authApi } from "./api";
import type { User } from "@/types";

// Re-export useAuth so consumers can import both the context provider and
// the hook from the same module. The hook itself lives in `./useAuth` so
// the type definitions stay tree-shakeable independent of the provider.
export { useAuth } from "./useAuth";

/**
 * Wraps the app and exposes the auth context. On mount it probes
 * /api/auth/me to decide whether the existing `cyclone_session`
 * cookie is still valid. Callers (route guard, sidebar, RoleGate,
 * Login page) read the resulting `status` + `user` via `useAuth()`.
 *
 *   - "loading"        → while the probe is in flight
 *   - "authenticated"  → probe succeeded; user populated
 *   - "unauthenticated"→ probe failed; user is null
 *
 * `login` and `logout` mutate local state directly so the UI flips
 * without waiting for a second /me round-trip.
 */
export function AuthProvider({ children }: { children: ReactNode }) {
  const [status, setStatus] = useState<AuthStatus>("loading");
  const [user, setUser] = useState<User | null>(null);

  const refresh = useCallback(async () => {
    setStatus("loading");
    try {
      const me = await authApi.me();
      setUser(me as User);
      setStatus("authenticated");
    } catch {
      setUser(null);
      setStatus("unauthenticated");
    }
  }, []);

  useEffect(() => {
    void refresh();
  }, [refresh]);

  const login = useCallback(async (username: string, password: string) => {
    const u = await authApi.login(username, password);
    setUser(u as User);
    setStatus("authenticated");
  }, []);

  const logout = useCallback(async () => {
    await authApi.logout().catch(() => undefined);
    setUser(null);
    setStatus("unauthenticated");
  }, []);

  const value: AuthContextValue = { status, user, login, logout, refresh };
  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
