import axios from 'axios' import type { AdminUser, AIProvider, Exam, PublicSettings, ScoreInput, SchoolLevel, Student, Subject, SystemSettings, TokenResponse, TrendResponse, User, WrongQuestion, WrongQuestionCategory, } from '../types' import type { ExamType } from '../types' const api = axios.create({ baseURL: '/api', }) api.interceptors.request.use((config) => { const token = localStorage.getItem('access_token') if (token) { config.headers.Authorization = `Bearer ${token}` } return config }) api.interceptors.response.use( (res) => res, async (error) => { const original = error.config if (error.response?.status === 401 && !original._retry) { original._retry = true const refresh = localStorage.getItem('refresh_token') if (refresh) { try { const { data } = await axios.post('/api/auth/refresh', { refresh_token: refresh, }) localStorage.setItem('access_token', data.access_token) localStorage.setItem('refresh_token', data.refresh_token) original.headers.Authorization = `Bearer ${data.access_token}` return api(original) } catch { localStorage.removeItem('access_token') localStorage.removeItem('refresh_token') window.location.href = '/login' } } } return Promise.reject(error) }, ) export const authApi = { register: (username: string, password: string) => api.post('/auth/register', { username, password }), login: (username: string, password: string) => api.post('/auth/login', { username, password }), me: () => api.get('/auth/me'), } export const settingsApi = { public: () => api.get('/settings/public'), } export const adminApi = { getSettings: () => api.get('/admin/settings'), updateSettings: (data: { registration_enabled?: boolean ai_provider?: AIProvider ollama_base_url?: string | null ollama_model?: string | null openai_base_url?: string | null openai_model?: string | null openai_api_key?: string ocr_service_url?: string | null }) => api.patch('/admin/settings', data), updateProfile: (data: { username?: string current_password?: string password?: string }) => api.patch('/admin/profile', data), listUsers: () => api.get('/admin/users'), createUser: (data: { username: string; password: string }) => api.post('/admin/users', data), resetUserPassword: (id: string, password: string) => api.patch(`/admin/users/${id}`, { password }), deleteUser: (id: string) => api.delete(`/admin/users/${id}`), } export const studentApi = { list: () => api.get('/students'), create: (data: { name: string school_level?: SchoolLevel grade?: string class_name?: string }) => api.post('/students', data), get: (id: string) => api.get(`/students/${id}`), update: (id: string, data: Partial) => api.patch(`/students/${id}`, data), remove: (id: string) => api.delete(`/students/${id}`), } export const subjectApi = { list: () => api.get('/subjects'), } export const examApi = { list: (studentId: string) => api.get(`/students/${studentId}/exams`), create: ( studentId: string, data: { exam_type: ExamType; exam_date: string; title?: string; scores: ScoreInput[] }, ) => api.post(`/students/${studentId}/exams`, data), update: ( examId: string, data: Partial<{ exam_type: ExamType; exam_date: string; title: string; scores: ScoreInput[] }>, ) => api.patch(`/exams/${examId}`, data), remove: (examId: string) => api.delete(`/exams/${examId}`), trend: (studentId: string, subjectId: number) => api.get(`/students/${studentId}/scores/trend`, { params: { subject_id: subjectId }, }), exportCsv: (studentId: string) => api.get(`/students/${studentId}/scores/export`, { responseType: 'blob' }), } export const wrongQuestionApi = { list: (studentId: string, params?: { subject_id?: number; q?: string; category?: WrongQuestionCategory }) => api.get(`/students/${studentId}/wrong-questions`, { params }), upload: (studentId: string, subjectId: number, file: File, category: WrongQuestionCategory = 'regular') => { const form = new FormData() form.append('subject_id', String(subjectId)) form.append('category', category) form.append('file', file) return api.post(`/students/${studentId}/wrong-questions`, form) }, get: (id: string) => api.get(`/wrong-questions/${id}`), update: (id: string, data: Partial) => api.patch(`/wrong-questions/${id}`, data), remove: (id: string) => api.delete(`/wrong-questions/${id}`), retryOcr: (id: string) => api.post(`/wrong-questions/${id}/retry-ocr`), regenerate: (id: string) => api.post(`/wrong-questions/${id}/regenerate-solution`), imageUrl: (id: string) => `/api/wrong-questions/${id}/image`, } export default api