import type { AdminDashboardResponse, AdminSeasonDetailResponse, AdminSeasonListItem, AuthSession, CreateClipPayload, CreateNominationPayload, CreateVotePayload, LoginPayload, OverviewResponse, SeasonCategoriesResponse, UpdateSeasonPayload, ApproveNominationPayload, UpsertCandidatePayload, UpsertCategoryPayload, WinnerArchiveResponse, } from '../types/awards' const API_URL = import.meta.env.VITE_API_URL ?? 'http://127.0.0.1:5084' const AUTH_TOKEN_KEY = 'vtsa-session-token' function getAuthToken() { if (typeof window === 'undefined') return null return window.localStorage.getItem(AUTH_TOKEN_KEY) } async function getJson(path: string): Promise { const token = getAuthToken() const response = await fetch(`${API_URL}${path}`, { headers: token ? { Authorization: `Bearer ${token}`, } : undefined, }).catch(() => { throw new Error(`API nicht erreichbar (${API_URL}). Bitte Backend starten.`) }) if (!response.ok) { throw new Error(`API request failed for ${path}`) } return response.json() as Promise } async function sendDelete(path: string): Promise { const token = getAuthToken() const response = await fetch(`${API_URL}${path}`, { method: 'DELETE', headers: token ? { Authorization: `Bearer ${token}` } : undefined, }).catch(() => { throw new Error(`API nicht erreichbar (${API_URL}). Bitte Backend starten.`) }) if (!response.ok) { const error = await response.text() throw new Error(error || `API request failed for ${path}`) } return response.json() as Promise } async function sendJson(path: string, method: 'POST' | 'PUT', body: unknown): Promise { const token = getAuthToken() const response = await fetch(`${API_URL}${path}`, { method, headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}), }, body: JSON.stringify(body), }).catch(() => { throw new Error(`API nicht erreichbar (${API_URL}). Bitte Backend starten.`) }) if (!response.ok) { const error = await response.text() throw new Error(error || `API request failed for ${path}`) } return response.json() as Promise } export const api = { getOverview: () => getJson('/api/public/overview'), getSeasonCategories: (year: number) => getJson(`/api/public/seasons/${year}/categories`), getWinnerArchive: (year: number) => getJson(`/api/public/seasons/${year}/winners`), getAdminDashboard: () => getJson('/api/admin/dashboard'), getAdminSeasons: () => getJson('/api/admin/seasons'), getAdminSeasonDetail: (seasonId: number) => getJson(`/api/admin/seasons/${seasonId}`), getSession: () => getJson('/api/auth/session'), login: (payload: LoginPayload) => sendJson('/api/auth/dev-login', 'POST', payload), logout: () => sendJson<{ loggedOut: boolean }>('/api/auth/logout', 'POST', {}), submitNomination: (payload: CreateNominationPayload) => sendJson<{ saved: number; category: string }>('/api/public/nominations', 'POST', payload), submitVote: (payload: CreateVotePayload) => sendJson<{ ballotId: number; entries: number }>('/api/public/votes', 'POST', payload), submitClip: (payload: CreateClipPayload) => sendJson<{ saved: boolean; clipId: number }>('/api/public/clips', 'POST', payload), updateAdminSeason: (seasonId: number, payload: UpdateSeasonPayload) => sendJson<{ saved: boolean; seasonId: number }>(`/api/admin/seasons/${seasonId}`, 'PUT', payload), createAdminCategory: (seasonId: number, payload: UpsertCategoryPayload) => sendJson<{ saved: boolean; categoryId: number }>(`/api/admin/seasons/${seasonId}/categories`, 'POST', payload), updateAdminCategory: (categoryId: number, payload: UpsertCategoryPayload) => sendJson<{ saved: boolean; categoryId: number }>(`/api/admin/categories/${categoryId}`, 'PUT', payload), createAdminCandidate: (seasonId: number, payload: UpsertCandidatePayload) => sendJson<{ saved: boolean; candidateId: number }>(`/api/admin/seasons/${seasonId}/candidates`, 'POST', payload), updateAdminCandidate: (candidateId: number, payload: UpsertCandidatePayload) => sendJson<{ saved: boolean; candidateId: number }>(`/api/admin/candidates/${candidateId}`, 'PUT', payload), deleteAdminCandidate: (candidateId: number) => sendDelete<{ deleted: boolean; candidateId: number }>(`/api/admin/candidates/${candidateId}`), deleteAdminCategory: (categoryId: number) => sendDelete<{ deleted: boolean; categoryId: number }>(`/api/admin/categories/${categoryId}`), deleteAdminClip: (clipId: number) => sendDelete<{ deleted: boolean; clipId: number }>(`/api/admin/clips/${clipId}`), approveAdminNomination: (nominationId: number, payload: ApproveNominationPayload) => sendJson<{ saved: boolean; nominationId: number; candidateId: number; created: boolean }>( `/api/admin/nominations/${nominationId}/approve`, 'POST', payload, ), rejectAdminNomination: (nominationId: number) => sendJson<{ saved: boolean; nominationId: number; rejected: boolean }>( `/api/admin/nominations/${nominationId}/reject`, 'POST', {}, ), resolveRiskFlag: (riskFlagId: number, status = 'resolved') => sendJson<{ saved: boolean; riskFlagId: number; status: string }>( `/api/admin/risk-flags/${riskFlagId}/resolve`, 'POST', { status }, ), } export { AUTH_TOKEN_KEY }