import axios, { AxiosError, InternalAxiosRequestConfig } from 'axios'; import type { TokenResponse, User, CompanyAnalysis, BatchAnalysisResult, JobStatus, Analytics } from '../types'; const API_BASE_URL = import.meta.env.VITE_API_URL || '/api'; const api = axios.create({ baseURL: API_BASE_URL, headers: { 'Content-Type': 'application/json', }, }); // Token management let accessToken: string | null = localStorage.getItem('access_token'); let refreshToken: string | null = localStorage.getItem('refresh_token'); export const setTokens = (tokens: TokenResponse) => { accessToken = tokens.access_token; refreshToken = tokens.refresh_token; localStorage.setItem('access_token', tokens.access_token); localStorage.setItem('refresh_token', tokens.refresh_token); }; export const clearTokens = () => { accessToken = null; refreshToken = null; localStorage.removeItem('access_token'); localStorage.removeItem('refresh_token'); }; export const getAccessToken = () => accessToken; // Request interceptor to add auth header api.interceptors.request.use((config: InternalAxiosRequestConfig) => { if (accessToken) { config.headers.Authorization = `Bearer ${accessToken}`; } return config; }); // Response interceptor to handle token refresh api.interceptors.response.use( (response) => response, async (error: AxiosError) => { const originalRequest = error.config as InternalAxiosRequestConfig & { _retry?: boolean }; if (error.response?.status === 401 && !originalRequest._retry && refreshToken) { originalRequest._retry = true; try { const response = await axios.post(`${API_BASE_URL}/auth/refresh`, { refresh_token: refreshToken, }); setTokens(response.data); originalRequest.headers.Authorization = `Bearer ${response.data.access_token}`; return api(originalRequest); } catch { clearTokens(); window.location.href = '/login'; } } return Promise.reject(error); } ); // Auth API export const authApi = { register: async (email: string, password: string): Promise => { const response = await api.post('/auth/register', { email, password }); return response.data; }, login: async (email: string, password: string): Promise => { const response = await api.post('/auth/login', { email, password }); setTokens(response.data); return response.data; }, getMe: async (): Promise => { const response = await api.get('/auth/me'); return response.data; }, logout: () => { clearTokens(); }, }; // Analysis API export const analysisApi = { analyzeCompany: async (companyName: string): Promise => { const response = await api.get(`/analyze/${encodeURIComponent(companyName)}`); return response.data; }, analyzeBatch: async (companies: string[], maxWorkers = 3): Promise => { const response = await api.post('/analyze/batch', { companies, max_workers: maxWorkers, }); return response.data; }, analyzeBatchAsync: async (companies: string[], maxWorkers = 3): Promise => { const response = await api.post('/analyze/batch/async', { companies, max_workers: maxWorkers, }); return response.data; }, getJobStatus: async (jobId: string): Promise => { const response = await api.get(`/jobs/${jobId}`); return response.data; }, listJobs: async (status?: string, limit = 10): Promise => { const params = new URLSearchParams(); if (status) params.append('status', status); params.append('limit', limit.toString()); const response = await api.get(`/jobs?${params}`); return response.data; }, }; // Analytics API export const analyticsApi = { getAnalytics: async (days = 30): Promise => { const response = await api.get(`/analytics?days=${days}`); return response.data; }, }; // Admin API export const adminApi = { listUsers: async (limit = 100, offset = 0): Promise => { const response = await api.get(`/admin/users?limit=${limit}&offset=${offset}`); return response.data; }, updateUserRole: async (userId: number, role: 'admin' | 'user'): Promise => { const response = await api.patch(`/admin/users/${userId}/role`, { role }); return response.data; }, deleteUser: async (userId: number): Promise => { await api.delete(`/admin/users/${userId}`); }, }; export default api;