import { useState, useCallback, useEffect } from "react"; import { fetchCodexUsage } from "@/lib/api/codexApi"; import { loadCodexAuth, saveCodexAuth, clearCodexAuth } from "@/lib/storage"; import { pickAndReadCodexAuth } from "@/lib/fileReader"; import type { CodexUsageResponse, CodexAuth } from "@/types/codex"; type Status = "idle" | "loading" | "success" | "error"; async function doFetch( auth: CodexAuth, set: { auth: (v: CodexAuth | null) => void; usage: (v: CodexUsageResponse | null) => void; status: (v: Status) => void; error: (v: string | null) => void; } ) { set.status("loading"); set.error(null); try { const data = await fetchCodexUsage(auth); set.usage(data); set.status("success"); } catch (e: unknown) { const msg = e instanceof Error ? e.message : "UNKNOWN_ERROR"; set.error(msg); set.status("error"); if (msg === "TOKEN_EXPIRED") { await clearCodexAuth(); set.auth(null); } } } export function useCodexUsage() { const [auth, setAuth] = useState(null); const [usage, setUsage] = useState(null); const [status, setStatus] = useState("idle"); const [error, setError] = useState(null); const setters = { auth: setAuth, usage: setUsage, status: setStatus, error: setError }; useEffect(() => { loadCodexAuth().then((stored) => { if (stored) setAuth(stored); }); }, []); useEffect(() => { if (auth) void doFetch(auth, setters); }, [auth]); const importAuthFile = useCallback(async () => { try { const parsed = await pickAndReadCodexAuth(); await saveCodexAuth(parsed); setAuth(parsed); setError(null); } catch (e: unknown) { const msg = e instanceof Error ? e.message : "UNKNOWN_ERROR"; if (msg !== "PICKER_CANCELLED") setError(msg); } }, []); const refresh = useCallback(async () => { if (!auth) return; await doFetch(auth, setters); }, [auth]); // Re-reads auth from storage and fetches fresh data. Call from useFocusEffect // so the dashboard stays current when credentials are saved from another tab. const reload = useCallback(async () => { const stored = await loadCodexAuth(); if (!stored) { setAuth(null); setUsage(null); setStatus("idle"); return; } // Always pass a fresh object so the [auth] effect fires even if the content // is identical (JSON.parse returns a new reference each time, which is fine). setAuth(stored); }, []); const clearAuth = useCallback(async () => { await clearCodexAuth(); setAuth(null); setUsage(null); setStatus("idle"); setError(null); }, []); return { auth, usage, status, error, importAuthFile, refresh, reload, clearAuth }; }