import { createContext, useContext } from "react";
import type { User } from "@/types";

/**
 * Tri-state lifecycle for the auth surface.
 *
 *   - "loading"        → we haven't asked /api/auth/me yet, or the result
 *                         is still in flight. Route guards render a
 *                         placeholder so we don't bounce the user to
 *                         /login before the cookie has had a chance to
 *                         prove itself.
 *   - "authenticated"  → /me returned a real User. The rest of the app
 *                         can safely render protected surfaces.
 *   - "unauthenticated"→ /me failed (no cookie, expired cookie, server
 *                         down). Route guards redirect to /login.
 */
export type AuthStatus = "loading" | "authenticated" | "unauthenticated";

export interface AuthContextValue {
  status: AuthStatus;
  user: User | null;
  /**
   * Authenticate against /api/auth/login. Throws `ApiError` on failure
   * (with `code` = "invalid_credentials" | "account_disabled" |
   * "rate_limited" | "error"). On success, status flips to
   * "authenticated" and `user` is populated.
   */
  login: (username: string, password: string) => Promise<void>;
  /**
   * Hit /api/auth/logout and clear local state. Always succeeds
   * locally — even if the server is unreachable, the operator is
   * effectively signed out from the SPA's perspective.
   */
  logout: () => Promise<void>;
  /**
   * Re-run the /api/auth/me probe. Useful after a profile edit on the
   * admin pages so the sidebar reflects the new role without a
   * full reload.
   */
  refresh: () => Promise<void>;
}

export const AuthContext = createContext<AuthContextValue | null>(null);

/**
 * Read the current auth context. Throws when used outside of an
 * `<AuthProvider>` so consumers fail loudly during development instead
 * of silently rendering the unauthenticated branch.
 */
export function useAuth(): AuthContextValue {
  const ctx = useContext(AuthContext);
  if (!ctx) {
    throw new Error("useAuth must be used inside <AuthProvider>");
  }
  return ctx;
}
