// AuthProvider — Phase 1
//
// Context React qui :
//   - écoute les changements de session Supabase Auth (login, logout, refresh)
//   - hydrate le rôle utilisateur depuis /api/me (la table allowed_users)
//   - expose useAuth() et window.useAuth() pour les composants
//   - expose window.authedFetch() pour les appels API avec Bearer JWT auto
//
// Le SDK Supabase doit être chargé AVANT ce script (window.supabaseClient
// doit exister). Cf. <script type="module"> dans Herbier.html.

const AuthContext = React.createContext({
  user: null,           // { id, email, role, displayName } ou null
  loading: true,        // true pendant l'hydratation initiale
  error: null,          // message d'erreur (ex. "Email non autorisé")
  signIn: async () => {},
  signOut: async () => {},
});

function AuthProvider({ children }) {
  const [state, setState] = React.useState({
    user: null,
    loading: true,
    error: null,
  });

  // ── Hydratation depuis /api/me ───────────────────────────────────────
  const hydrateFromSession = React.useCallback(async (session) => {
    if (!session?.access_token) {
      setState({ user: null, loading: false, error: null });
      return;
    }
    try {
      const res = await fetch("/api/me", {
        headers: { Authorization: `Bearer ${session.access_token}` },
        cache: "no-store",
      });
      if (res.status === 403) {
        // Email connecté Supabase Auth mais pas dans allowed_users : déconnexion
        // automatique + message clair.
        const { error } = await res.json();
        const sb = window.supabaseClient;
        if (sb) await sb.auth.signOut();
        setState({
          user: null,
          loading: false,
          error: error || "Cet email n'est pas autorisé à accéder au recueil.",
        });
        return;
      }
      if (!res.ok) {
        const body = await res.json().catch(() => ({}));
        setState({
          user: null,
          loading: false,
          error: body.error || `Erreur d'authentification serveur (HTTP ${res.status}).`,
        });
        return;
      }
      const { user } = await res.json();
      setState({ user, loading: false, error: null });
    } catch (e) {
      // Échec réseau : serveur arrêté, déconnexion Wi-Fi, etc.
      console.error("[AuthProvider] /api/me network error:", e);
      setState({
        user: null,
        loading: false,
        error: "Impossible de joindre le serveur. Vérifie que l'API est démarrée (vercel dev) ou ta connexion internet.",
      });
    }
  }, []);

  React.useEffect(() => {
    const sb = window.supabaseClient;
    if (!sb) {
      // Cas exceptionnel : SDK pas chargé. On marque loading=false pour ne
      // pas bloquer l'app et on log l'erreur.
      console.error("[AuthProvider] window.supabaseClient indisponible — vérifier le <script type=\"module\"> dans Herbier.html");
      setState({ user: null, loading: false, error: null });
      return;
    }

    // Session existante (refresh / réouverture d'onglet)
    sb.auth.getSession().then(({ data }) => {
      hydrateFromSession(data?.session);
    });

    // Listener pour login/logout/refresh
    const { data: sub } = sb.auth.onAuthStateChange((_event, session) => {
      hydrateFromSession(session);
    });

    return () => sub?.subscription?.unsubscribe?.();
  }, [hydrateFromSession]);

  // ── Méthodes exposées ────────────────────────────────────────────────
  const signIn = React.useCallback(async (email) => {
    const sb = window.supabaseClient;
    if (!sb) throw new Error("Supabase non initialisé");
    const { error } = await sb.auth.signInWithOtp({
      email: email.toLowerCase().trim(),
      options: {
        emailRedirectTo: window.location.origin + "/Herbier.html",
      },
    });
    if (error) throw error;
    return { ok: true };
  }, []);

  const signOut = React.useCallback(async () => {
    const sb = window.supabaseClient;
    if (!sb) return;
    await sb.auth.signOut();
    setState({ user: null, loading: false, error: null });
  }, []);

  const clearError = React.useCallback(() => {
    setState(prev => ({ ...prev, error: null }));
  }, []);

  const value = React.useMemo(() => ({
    ...state,
    signIn,
    signOut,
    clearError,
  }), [state, signIn, signOut, clearError]);

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

const useAuth = () => React.useContext(AuthContext);

// ─────────────────────────────────────────────────────────────────────────
// window.authedFetch — wrapper fetch qui ajoute le JWT Bearer si dispo.
// À utiliser pour TOUS les appels POST aux endpoints /api/* qui nécessitent
// l'auth (save, set-default-photo, delete, et plus tard submit-revision).
//
// Usage :
//   const res = await window.authedFetch("/api/save", {
//     method: "POST",
//     headers: { "Content-Type": "application/json" },
//     body: JSON.stringify(...)
//   });
//
// Si l'utilisateur n'est pas connecté, le header n'est juste pas ajouté —
// le serveur retournera 401, à charge de l'appelant d'afficher un message.
// ─────────────────────────────────────────────────────────────────────────
window.authedFetch = async function authedFetch(url, init = {}) {
  const sb = window.supabaseClient;
  let token = null;
  if (sb) {
    try {
      const { data } = await sb.auth.getSession();
      token = data?.session?.access_token || null;
    } catch {}
  }
  const headers = { ...(init.headers || {}) };
  if (token) headers.Authorization = `Bearer ${token}`;
  return fetch(url, { ...init, headers });
};

// Expose pour les composants JSX chargés en parallèle (Babel inline n'utilise
// pas d'imports, tout passe par window).
window.useAuth = useAuth;
window.AuthProvider = AuthProvider;
window.AuthContext = AuthContext;
