import { BotInfo, BotStatus, GuildSummary, GuildDetails, PrefixConfig, AutomodConfig, TicketConfig, LevelingConfig, LoggingConfig, PrefixUpdate, AutomodUpdate, LevelingUpdate, LoggingUpdate, LeaderboardEntry, DiscordChannel, DiscordRole, AutoRoleConfig, AutoRoleUpdate, AdminStats, AdminConfig, AdminConfigUpdate } from "@/types/api"; const BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000/api/v1"; const API_KEY = process.env.NEXT_PUBLIC_DASHBOARD_API_KEY; class ApiError extends Error { constructor(public status: number, message: string) { super(message); this.name = "ApiError"; } } async function request( endpoint: string, options: RequestInit & { next?: NextFetchRequestConfig } = {} ): Promise { const url = `${BASE_URL}${endpoint}`; const headers = new Headers(options.headers); if (API_KEY) { headers.set("Authorization", `Bearer ${API_KEY}`); } headers.set("Content-Type", "application/json"); try { const response = await fetch(url, { ...options, headers, // CRITICAL: Never cache mutation responses. For GETs, use revalidate: 0 // to always fetch fresh data from the bot API. Caching was causing // saved data to "disappear" on reload because Next.js served stale cache. next: options.next || { revalidate: 0 }, }); if (!response.ok) { let errorData; try { errorData = await response.json(); } catch { errorData = { detail: "An unknown error occurred" }; } console.error(`[API HTTP Error] Status ${response.status} for ${url}:`, errorData); throw new ApiError(response.status, errorData.detail || response.statusText); } return response.json(); } catch (error) { console.error(`[API Network/Fetch Error] Failed to fetch ${url}:`, error); throw error; } } export const api = { // Bot getBotStatus: () => request("/bot/status"), getBotInfo: () => request("/bot/info"), // Guilds listGuilds: () => request("/guilds/"), getGuildDetails: (guildId: string) => request(`/guilds/${guildId}`), getChannels: (guildId: string) => request(`/guilds/${guildId}/channels`), getRoles: (guildId: string) => request(`/guilds/${guildId}/roles`), // Module Configs getPrefix: (guildId: string) => request(`/guilds/${guildId}/prefix`), updatePrefix: (guildId: string, prefix: string) => request<{ status: string; new_prefix: string }>(`/guilds/${guildId}/prefix`, { method: "POST", body: JSON.stringify({ prefix }), }), getAutomod: (guildId: string) => request(`/guilds/${guildId}/automod`), updateAutomod: (guildId: string, data: Partial) => request<{ status: string }>(`/guilds/${guildId}/automod`, { method: "PATCH", body: JSON.stringify(data), }), getTickets: (guildId: string) => request(`/guilds/${guildId}/tickets`), updateTickets: (guildId: string, data: any) => request<{ status: string }>(`/guilds/${guildId}/tickets`, { method: "PATCH", body: JSON.stringify(data), }), getLeveling: (guildId: string) => request(`/guilds/${guildId}/leveling`), updateLeveling: (guildId: string, data: any) => request<{ status: string }>(`/guilds/${guildId}/leveling`, { method: "PATCH", body: JSON.stringify(data), }), getLogging: (guildId: string) => request(`/guilds/${guildId}/logging`), updateLogging: (guildId: string, data: any) => request<{ status: string }>(`/guilds/${guildId}/logging`, { method: "PATCH", body: JSON.stringify(data), }), getLeaderboard: (guildId: string) => request(`/guilds/${guildId}/leveling/leaderboard`), getWelcome: (guildId: string) => request(`/guilds/${guildId}/welcome`), updateWelcome: (guildId: string, data: any) => request<{ status: string }>(`/guilds/${guildId}/welcome`, { method: "PATCH", body: JSON.stringify(data), }), getAntiNuke: (guildId: string) => request(`/guilds/${guildId}/antinuke`), updateAntiNuke: (guildId: string, data: any) => request<{ status: string }>(`/guilds/${guildId}/antinuke`, { method: "PATCH", body: JSON.stringify(data), }), getVerification: (guildId: string) => request(`/guilds/${guildId}/verification`), updateVerification: (guildId: string, data: any) => request<{ status: string }>(`/guilds/${guildId}/verification`, { method: "PATCH", body: JSON.stringify(data), }), getVanityRoles: (guildId: string) => request(`/guilds/${guildId}/vanityroles`), addVanityRole: (guildId: string, data: any) => request<{ status: string }>(`/guilds/${guildId}/vanityroles`, { method: "POST", body: JSON.stringify(data), }), deleteVanityRole: (guildId: string, vanity: string) => request<{ status: string }>(`/guilds/${guildId}/vanityroles/${vanity}`, { method: "DELETE", }), getAutoRole: (guildId: string) => request(`/guilds/${guildId}/autorole`), updateAutoRole: (guildId: string, data: AutoRoleUpdate) => request<{ status: string }>(`/guilds/${guildId}/autorole`, { method: "PATCH", body: JSON.stringify(data), }), getTracking: (guildId: string) => request(`/guilds/${guildId}/tracking`), updateTracking: (guildId: string, data: any) => request<{ status: string }>(`/guilds/${guildId}/tracking`, { method: "PATCH", body: JSON.stringify(data), }), getJ2C: (guildId: string) => request(`/guilds/${guildId}/j2c`), updateJ2C: (guildId: string, data: any) => request<{ status: string }>(`/guilds/${guildId}/j2c`, { method: "PATCH", body: JSON.stringify(data), }), getJoinDM: (guildId: string) => request(`/guilds/${guildId}/joindm`), updateJoinDM: (guildId: string, data: any) => request<{ status: string }>(`/guilds/${guildId}/joindm`, { method: "PATCH", body: JSON.stringify(data), }), getCustomRoles: (guildId: string) => request(`/guilds/${guildId}/customroles`), updateCustomRoles: (guildId: string, data: any) => request<{ status: string }>(`/guilds/${guildId}/customroles`, { method: "PATCH", body: JSON.stringify(data), }), getAutoReact: (guildId: string) => request(`/guilds/${guildId}/autoreact`), updateAutoReact: (guildId: string, data: any) => request<{ status: string }>(`/guilds/${guildId}/autoreact`, { method: "PATCH", body: JSON.stringify(data), }), getInvcRole: (guildId: string) => request(`/guilds/${guildId}/invcrole`), updateInvcRole: (guildId: string, data: any) => request<{ status: string }>(`/guilds/${guildId}/invcrole`, { method: "PATCH", body: JSON.stringify(data), }), getRR: (guildId: string) => request(`/guilds/${guildId}/reactionroles`), updateRR: (guildId: string, data: any) => request<{ status: string }>(`/guilds/${guildId}/reactionroles`, { method: "PATCH", body: JSON.stringify(data), }), getInvites: (guildId: string) => request(`/guilds/${guildId}/invites`), updateInvites: (guildId: string, data: any) => request<{ status: string }>(`/guilds/${guildId}/invites`, { method: "PATCH", body: JSON.stringify(data), }), // Admin getAdminStats: () => request("/admin/stats"), getAdminConfig: () => request("/admin/config"), updateAdminConfig: (data: AdminConfigUpdate) => request<{ status: string }>("/admin/config", { method: "PATCH", body: JSON.stringify(data), }), };