import axios from "axios"

const ADMIN_ACCESS_KEY = "admin_access_token"
const ADMIN_REFRESH_KEY = "admin_refresh_token"

const adminClient = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL || "/api",
  timeout: 10000,
  headers: { "Content-Type": "application/json" },
})

adminClient.interceptors.request.use((config) => {
  const token = localStorage.getItem(ADMIN_ACCESS_KEY)
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  return config
})

let isRefreshing = false
let failedQueue: Array<{
  resolve: (token: string) => void
  reject: (error: unknown) => void
}> = []

const processQueue = (error: unknown, token: string | null = null) => {
  failedQueue.forEach((p) => {
    if (error) p.reject(error)
    else p.resolve(token!)
  })
  failedQueue = []
}

const AUTH_PUBLIC_PATHS = ["/v1/admin/auth/login", "/v1/admin/auth/refresh"]

function isCommercialCode(code: unknown): boolean {
  return typeof code === "number" && code >= 6100 && code < 6200
}

export function isCommercialError(error: unknown): boolean {
  const code = (error as { response?: { data?: { code?: unknown } } })?.response?.data?.code
  return isCommercialCode(code)
}

adminClient.interceptors.response.use(
  (response) => response,
  async (error) => {
    const originalRequest = error.config
    const url: string = originalRequest?.url || ""
    const isAuthPublic = AUTH_PUBLIC_PATHS.some((p) => url.includes(p))

    const businessCode = error.response?.data?.code
    if (isCommercialCode(businessCode)) {
      const { toast } = await import("../../utils/toast")
      toast.error(error.response?.data?.message || "该站点暂不支持此功能")
      return Promise.reject(error)
    }

    if (error.response?.status === 401 && !originalRequest._retry && !isAuthPublic) {
      if (isRefreshing) {
        return new Promise((resolve, reject) => {
          failedQueue.push({ resolve, reject })
        }).then((token) => {
          originalRequest.headers.Authorization = `Bearer ${token}`
          return adminClient(originalRequest)
        })
      }

      originalRequest._retry = true
      isRefreshing = true

      try {
        const refreshToken = localStorage.getItem(ADMIN_REFRESH_KEY)
        if (!refreshToken) throw new Error("No refresh token")

        const { data } = await axios.post("/api/v1/admin/auth/refresh", {
          refresh_token: refreshToken,
        })

        const newAccess = data.data.access_token
        const newRefresh = data.data.refresh_token

        localStorage.setItem(ADMIN_ACCESS_KEY, newAccess)
        localStorage.setItem(ADMIN_REFRESH_KEY, newRefresh)

        processQueue(null, newAccess)
        originalRequest.headers.Authorization = `Bearer ${newAccess}`
        return adminClient(originalRequest)
      } catch (refreshError) {
        processQueue(refreshError, null)
        localStorage.removeItem(ADMIN_ACCESS_KEY)
        localStorage.removeItem(ADMIN_REFRESH_KEY)
        window.dispatchEvent(new CustomEvent("admin:unauthorized"))
        return Promise.reject(refreshError)
      } finally {
        isRefreshing = false
      }
    }

    return Promise.reject(error)
  },
)

export { ADMIN_ACCESS_KEY, ADMIN_REFRESH_KEY }
export default adminClient
