import axios, { AxiosError } from "axios"
import { useAuthStore } from "@/store/authStore"
import type { ApiResult } from "@/types/api"
import { extractMessageFromBody } from "@/lib/errors"

function toCamelCase(s: string): string {
  return s.replace(/_([a-z])/g, (_, c) => c.toUpperCase())
}

function transformKeys(obj: unknown): unknown {
  if (Array.isArray(obj)) return obj.map(transformKeys)
  if (obj !== null && typeof obj === "object") {
    const result: Record<string, unknown> = {}
    for (const [k, v] of Object.entries(obj as Record<string, unknown>)) {
      result[toCamelCase(k)] = transformKeys(v)
    }
    return result
  }
  return obj
}

const client = axios.create({
  baseURL: localStorage.getItem("api_base_url") || "",
  timeout: 15000,
})

client.interceptors.request.use((config) => {
  const token = useAuthStore.getState().token
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  return config
})

function isLoginPage(): boolean {
  return window.location.pathname === "/login" || window.location.pathname === "/"
}

client.interceptors.response.use(
  (response) => {
    const body = response.data as ApiResult<unknown>
    if (body.code !== 200) {
      if (body.code === 401) {
        useAuthStore.getState().clearAuth()
        if (!isLoginPage()) window.location.href = "/login"
      }
      const msg = extractMessageFromBody(body) ?? "请求失败"
      throw new Error(msg)
    }
    response.data = transformKeys(body) as ApiResult<unknown>
    return response
  },
  (error: AxiosError<ApiResult<unknown>>) => {
    if (!navigator.onLine) {
      throw new Error("网络连接失败，请检查网络")
    }
    const data = error.response?.data
    if (data) {
      if (data.code === 401) {
        useAuthStore.getState().clearAuth()
        if (!isLoginPage()) window.location.href = "/login"
      }
      const msg = extractMessageFromBody(data) ?? "请求失败"
      throw new Error(msg)
    }
    if (error.code === "ERR_NETWORK" || error.code === "ECONNABORTED") {
      throw new Error("网络连接失败，请检查网络")
    }
    throw error
  }
)

export function setBaseUrl(url: string) {
  client.defaults.baseURL = url
  localStorage.setItem("api_base_url", url)
}

export default client
