import type { CategoryListResponse, Pattern, PatternListResponse, PatternTutorial, QuestionDetail, QuestionListResponse, Stats, SubmissionRequest, SubmissionResponse, } from "@/types"; // Server-side uses internal Docker network, client-side uses public URL const API_BASE_URL = typeof window === "undefined" ? process.env.API_URL || "http://localhost:8000" : process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000"; export class ApiError extends Error { constructor( public status: number, public statusText: string, public detail?: string ) { super(detail || `API error: ${status} ${statusText}`); this.name = "ApiError"; } } async function fetchApi( endpoint: string, options?: RequestInit ): Promise { const url = `${API_BASE_URL}${endpoint}`; const response = await fetch(url, { ...options, headers: { "Content-Type": "application/json", ...options?.headers, }, }); if (!response.ok) { let detail: string | undefined; try { const errorBody = await response.json(); detail = errorBody.detail; } catch { // Ignore JSON parse errors } throw new ApiError(response.status, response.statusText, detail); } return response.json(); } export interface QuestionFilters { page?: number; limit?: number; difficulty?: string; category?: string; pattern?: string; search?: string; } export async function getQuestions( filters: QuestionFilters = {} ): Promise { const params = new URLSearchParams(); if (filters.page) params.set("page", filters.page.toString()); if (filters.limit) params.set("limit", filters.limit.toString()); if (filters.difficulty) params.set("difficulty", filters.difficulty); if (filters.category) params.set("category", filters.category); if (filters.pattern) params.set("pattern", filters.pattern); if (filters.search) params.set("search", filters.search); const queryString = params.toString(); const endpoint = queryString ? `/api/questions?${queryString}` : "/api/questions"; return fetchApi(endpoint); } export async function getQuestion(slug: string): Promise { return fetchApi(`/api/questions/${slug}`); } export async function getCategories(): Promise { return fetchApi("/api/categories"); } export async function getPatterns(): Promise { return fetchApi("/api/patterns"); } export async function getPattern(slug: string): Promise { return fetchApi(`/api/patterns/${slug}`); } export async function getPatternTutorial(slug: string): Promise { return fetchApi(`/api/patterns/${slug}/tutorial`); } export async function getStats(): Promise { return fetchApi("/api/stats"); } export async function submitSolution( slug: string, submission: SubmissionRequest ): Promise { return fetchApi(`/api/questions/${slug}/submit`, { method: "POST", body: JSON.stringify(submission), }); }