// AuthProvider — backend-mediated OIDC login.
//
// Flow:
//   1. On mount, GET /api/auth/oidc/status to learn if OIDC is configured.
//   2. GET /api/auth/me — if session cookie exists + valid → set user.
//   3. If anon + click Login → window.location = /api/auth/oidc/start
//   4. Backend 302's to IdP → IdP 302's back to /api/auth/oidc/callback
//      → backend 302's to /oidc/callback#oidc_ticket=... on this SPA.
//   5. <OidcCallbackPage> reads the fragment, POST /api/auth/oidc/exchange,
//      backend sets the dialectic_session cookie, redirects to /.
//   6. Logout: POST /api/auth/logout (clears cookie) → useAuth refetches.
//
// The session JWT lives only in an HttpOnly cookie; the SPA never sees
// the raw token. /api/auth/me is the canonical "who am I" probe.

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

interface User {
  id: string;
  email: string;
  name: string;
}

interface AuthCtx {
  user: User | null;
  loading: boolean;
  oidcEnabled: boolean;
  login: () => void;
  logout: () => Promise<void>;
  refresh: () => Promise<void>;
}

const Ctx = createContext<AuthCtx>({
  user: null,
  loading: true,
  oidcEnabled: false,
  login: () => {},
  logout: async () => {},
  refresh: async () => {},
});

const API_BASE = import.meta.env.VITE_DIALECTIC_API_BASE ?? '/api';

async function fetchStatus(): Promise<boolean> {
  try {
    const r = await fetch(`${API_BASE}/auth/oidc/status`);
    if (!r.ok) return false;
    const j = await r.json();
    return Boolean(j.enabled);
  } catch {
    return false;
  }
}

async function fetchMe(): Promise<User | null> {
  try {
    const r = await fetch(`${API_BASE}/auth/me`, { credentials: 'same-origin' });
    if (r.status === 401) return null;
    if (!r.ok) return null;
    return (await r.json()) as User;
  } catch {
    return null;
  }
}

export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState(true);
  const [oidcEnabled, setOidcEnabled] = useState(false);

  const refresh = useCallback(async () => {
    setLoading(true);
    const [enabled, me] = await Promise.all([fetchStatus(), fetchMe()]);
    setOidcEnabled(enabled);
    setUser(me);
    setLoading(false);
  }, []);

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

  const login = useCallback(() => {
    // Hard navigation — backend builds the IdP URL + redirects.
    window.location.href = `${API_BASE}/auth/oidc/start`;
  }, []);

  const logout = useCallback(async () => {
    await fetch(`${API_BASE}/auth/logout`, {
      method: 'POST',
      credentials: 'same-origin',
    });
    setUser(null);
  }, []);

  return (
    <Ctx.Provider value={{ user, loading, oidcEnabled, login, logout, refresh }}>
      {children}
    </Ctx.Provider>
  );
}

export function useAuth(): AuthCtx {
  return useContext(Ctx);
}
