import { useEffect, useState } from "preact/hooks"; import { getConfiguredToken, setAuthToken, verifySession } from "@/lib/api"; const TOKEN_STORAGE_KEY = "sybil_admin_token"; export type AuthMode = "open" | "token"; function readStoredToken() { return localStorage.getItem(TOKEN_STORAGE_KEY)?.trim() || null; } function persistToken(token: string | null) { if (token) { localStorage.setItem(TOKEN_STORAGE_KEY, token); return; } localStorage.removeItem(TOKEN_STORAGE_KEY); } function normalizeAuthError(message: string) { if (message.includes("missing bearer token") || message.includes("invalid bearer token")) { return "Authentication failed. Enter the ADMIN_TOKEN configured in server/.env."; } return message; } export function useSessionAuth() { const initialToken = readStoredToken() ?? getConfiguredToken() ?? ""; const [authTokenInput, setAuthTokenInput] = useState(initialToken); const [isCheckingSession, setIsCheckingSession] = useState(true); const [isSigningIn, setIsSigningIn] = useState(false); const [isAuthenticated, setIsAuthenticated] = useState(false); const [authMode, setAuthMode] = useState(null); const [authError, setAuthError] = useState(null); const completeSessionCheck = async (tokenCandidate: string | null) => { setAuthToken(tokenCandidate); const session = await verifySession(); setIsAuthenticated(true); setAuthMode(session.mode); setAuthError(null); persistToken(tokenCandidate); }; const handleAuthFailure = (message: string) => { setIsAuthenticated(false); setAuthMode(null); setAuthError(normalizeAuthError(message)); setAuthToken(null); persistToken(null); }; const handleSignIn = async (tokenCandidate: string | null) => { setIsSigningIn(true); setAuthError(null); try { await completeSessionCheck(tokenCandidate); } catch (err) { const message = err instanceof Error ? err.message : String(err); setAuthError(normalizeAuthError(message)); setIsAuthenticated(false); setAuthMode(null); } finally { setIsSigningIn(false); } }; const logout = () => { setAuthToken(null); persistToken(null); setIsAuthenticated(false); setAuthMode(null); setAuthError(null); }; useEffect(() => { const token = readStoredToken() ?? getConfiguredToken(); void (async () => { try { await completeSessionCheck(token); } catch (err) { const message = err instanceof Error ? err.message : String(err); handleAuthFailure(message); } finally { setIsCheckingSession(false); } })(); }, []); return { authTokenInput, setAuthTokenInput, isCheckingSession, isSigningIn, isAuthenticated, authMode, authError, handleAuthFailure, handleSignIn, logout, }; }