import axios from 'axios'
import type {
  AdminUser,
  AIProvider,
  AppFeatures,
  BackupInfo,
  Composition,
  CompositionInputMode,
  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<TokenResponse>('/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<User>('/auth/register', { username, password }),
  login: (username: string, password: string) =>
    api.post<TokenResponse>('/auth/login', { username, password }),
  me: () => api.get<User>('/auth/me'),
}

export const settingsApi = {
  public: () => api.get<PublicSettings>('/settings/public'),
  appFeatures: () => api.get<AppFeatures>('/settings/app-features'),
}

export const adminApi = {
  getSettings: () => api.get<SystemSettings>('/admin/settings'),
  updateSettings: (data: {
    registration_enabled?: boolean
    ai_review_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<SystemSettings>('/admin/settings', data),
  updateProfile: (data: {
    username?: string
    current_password?: string
    password?: string
  }) => api.patch<AdminUser>('/admin/profile', data),
  listUsers: () => api.get<AdminUser[]>('/admin/users'),
  createUser: (data: { username: string; password: string }) =>
    api.post<AdminUser>('/admin/users', data),
  resetUserPassword: (id: string, password: string) =>
    api.patch<AdminUser>(`/admin/users/${id}`, { password }),
  deleteUser: (id: string) => api.delete(`/admin/users/${id}`),
  listBackups: () => api.get<BackupInfo[]>('/admin/backups'),
  runBackup: () => api.post<BackupInfo>('/admin/backups/run'),
  downloadBackup: (filename: string) =>
    api.get(`/admin/backups/${encodeURIComponent(filename)}/download`, { responseType: 'blob' }),
  restoreBackup: (file: File) => {
    const form = new FormData()
    form.append('file', file)
    return api.post<{ ok: boolean; message: string }>('/admin/backups/restore', form)
  },
}

export const studentApi = {
  list: () => api.get<Student[]>('/students'),
  create: (data: {
    name: string
    school_level?: SchoolLevel
    school_name?: string
    grade?: string
    class_name?: string
  }) => api.post<Student>('/students', data),
  get: (id: string) => api.get<Student>(`/students/${id}`),
  update: (
    id: string,
    data: Partial<{
      name: string
      school_level: SchoolLevel
      school_name: string
      grade: string
      class_name: string
    }>,
  ) => api.patch<Student>(`/students/${id}`, data),
  remove: (id: string) => api.delete(`/students/${id}`),
  uploadAvatar: (id: string, file: File) => {
    const form = new FormData()
    form.append('file', file)
    return api.post<Student>(`/students/${id}/avatar`, form)
  },
  removeAvatar: (id: string) => api.delete<Student>(`/students/${id}/avatar`),
}

export const subjectApi = {
  list: () => api.get<Subject[]>('/subjects'),
}

export const examApi = {
  list: (studentId: string) => api.get<Exam[]>(`/students/${studentId}/exams`),
  create: (
    studentId: string,
    data: { exam_type: ExamType; exam_date: string; title?: string; scores: ScoreInput[] },
  ) => api.post<Exam>(`/students/${studentId}/exams`, data),
  update: (
    examId: string,
    data: Partial<{ exam_type: ExamType; exam_date: string; title: string; scores: ScoreInput[] }>,
  ) => api.patch<Exam>(`/exams/${examId}`, data),
  updateReview: (
    examId: string,
    reviews: { subject_id: number; review_statuses: ScoreInput['review_statuses'] }[],
  ) => api.patch<Exam>(`/exams/${examId}/review`, { reviews }),
  remove: (examId: string) => api.delete(`/exams/${examId}`),
  trend: (studentId: string, subjectId: number) =>
    api.get<TrendResponse>(`/students/${studentId}/scores/trend`, {
      params: { subject_id: subjectId },
    }),
  exportCsv: (studentId: string) =>
    api.get<Blob>(`/students/${studentId}/scores/export`, {
      responseType: 'blob',
      validateStatus: (status) => status >= 200 && status < 300,
    }),
  reviewInsight: (studentId: string, subjectName: string) =>
    api.post<{ insight: string }>(`/students/${studentId}/review-insight`, {
      subject_name: subjectName,
    }),
}

export const compositionApi = {
  list: (studentId: string) => api.get<Composition[]>(`/students/${studentId}/compositions`),
  create: (studentId: string, data: { topic: string; input_mode?: CompositionInputMode }) =>
    api.post<Composition>(`/students/${studentId}/compositions`, data),
  get: (id: string) => api.get<Composition>(`/compositions/${id}`),
  remove: (id: string) => api.delete(`/compositions/${id}`),
  regenerate: (id: string) => api.post<Composition>(`/compositions/${id}/regenerate`),
  ocr: (studentId: string, file: File) => {
    const form = new FormData()
    form.append('file', file)
    return api.post<{ text: string }>(`/students/${studentId}/compositions/ocr`, form)
  },
  download: (id: string) =>
    api.get(`/compositions/${id}/download`, { responseType: 'blob' }),
}

export const wrongQuestionApi = {
  list: (studentId: string, params?: { subject_id?: number; q?: string; category?: WrongQuestionCategory }) =>
    api.get<WrongQuestion[]>(`/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<WrongQuestion>(`/students/${studentId}/wrong-questions`, form)
  },
  get: (id: string) => api.get<WrongQuestion>(`/wrong-questions/${id}`),
  update: (id: string, data: Partial<WrongQuestion>) =>
    api.patch<WrongQuestion>(`/wrong-questions/${id}`, data),
  remove: (id: string) => api.delete(`/wrong-questions/${id}`),
  retryOcr: (id: string) => api.post<WrongQuestion>(`/wrong-questions/${id}/retry-ocr`),
  regenerate: (id: string) =>
    api.post<WrongQuestion>(`/wrong-questions/${id}/regenerate-solution`),
  imageUrl: (id: string) => `/api/wrong-questions/${id}/image`,
}

export default api
