import type { Book, BookDetail, CreatePlanPayload, GoogleAuthResponse, Plan, PlanDayDetail, PlanSummary, } from "./types"; import { getDemoBook, getDemoBooks, getDemoPlan, getDemoPlanDay, getDemoPlans, registerDemoPlan, } from "./demo-data"; const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://127.0.0.1:8000"; export const DEMO_MODE = process.env.NODE_ENV === "production" && !process.env.NEXT_PUBLIC_API_BASE_URL; async function demoRequest(path: string, init?: RequestInit): Promise { const [pathname] = path.split("?"); if (pathname === "/auth/google") { return { user_id: "demo-user", email: "demo@pluckai.local", display_name: "Demo User", } as T; } if (pathname === "/books") { return getDemoBooks() as T; } if (pathname.startsWith("/books/")) { const slug = decodeURIComponent(pathname.slice("/books/".length)); return getDemoBook(slug) as T; } if (pathname.startsWith("/users/") && pathname.endsWith("/plans")) { const email = decodeURIComponent(pathname.slice("/users/".length, -"/plans".length)); return getDemoPlans(email) as T; } if (pathname === "/plans" && init?.method?.toUpperCase() === "POST") { const body = typeof init.body === "string" ? init.body : "{}"; return registerDemoPlan(JSON.parse(body) as CreatePlanPayload) as T; } if (pathname.startsWith("/plans/") && pathname.includes("/days/")) { const segments = pathname.split("/"); const planId = decodeURIComponent(segments[2] ?? ""); const dayValue = Number(segments[4] ?? "1"); return getDemoPlanDay(planId, dayValue) as T; } if (pathname.startsWith("/plans/")) { const planId = decodeURIComponent(pathname.slice("/plans/".length)); return getDemoPlan(planId) as T; } throw new Error(`No demo response available for ${pathname}`); } async function request(path: string, init?: RequestInit): Promise { if (DEMO_MODE) { return demoRequest(path, init); } const response = await fetch(`${API_BASE_URL}${path}`, { ...init, headers: { "Content-Type": "application/json", ...(init?.headers || {}), }, cache: "no-store", }); if (!response.ok) { let message = response.statusText; try { const payload = await response.json(); message = payload.detail || payload.error || JSON.stringify(payload); } catch { // ignore body parse errors } throw new Error(message); } return (await response.json()) as T; } export const api = { verifyGoogleToken: (idToken: string) => request("/auth/google", { method: "POST", body: JSON.stringify({ id_token: idToken }), }), listBooks: () => request("/books"), getBook: (slug: string) => request(`/books/${slug}`), listPlans: (email: string) => request(`/users/${encodeURIComponent(email)}/plans`), createPlan: (payload: CreatePlanPayload) => request("/plans", { method: "POST", body: JSON.stringify(payload) }), getPlan: (planId: string) => request(`/plans/${planId}`), getPlanDay: (planId: string, dayNumber: number) => request(`/plans/${planId}/days/${dayNumber}`), };