import axios, { type AxiosError, type InternalAxiosRequestConfig } from 'axios'
import { ElMessage } from 'element-plus'

type HandledError = Error & {
  handled?: boolean
  status?: number
}

const request = axios.create({
  baseURL: (import.meta as any).env?.VITE_API_BASE_URL || '/api/v1',
  timeout: 30000,
})

function isAuthEndpoint(url?: string) {
  return !!url && ['/auth/login', '/auth/refresh'].some((path) => url.includes(path))
}

function getErrorMessage(data: any, fallback: string) {
  if (Array.isArray(data?.detail)) {
    return data.detail.map((d: any) => d.msg || JSON.stringify(d)).join(', ')
  }
  return data?.detail || data?.message || fallback
}

function makeHandledError(message: string, status?: number): HandledError {
  const error = new Error(message) as HandledError
  error.handled = true
  error.status = status
  return error
}

request.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    const token = localStorage.getItem('dp_token')
    if (token && config.headers && !isAuthEndpoint(config.url)) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

request.interceptors.response.use(
  (response) => {
    const res = response.data
    if (res.code !== 200) {
      const message = res.message || '请求失败'
      ElMessage.error(message)
      return Promise.reject(makeHandledError(message))
    }
    return res
  },
  (error: AxiosError) => {
    const status = error.response?.status
    const data = error.response?.data as any
    const message = getErrorMessage(data, error.message || '网络错误')
    if (status === 401) {
      localStorage.removeItem('dp_token')
      localStorage.removeItem('dp_refresh')

      if (isAuthEndpoint(error.config?.url)) {
        return Promise.reject(new Error(message || '用户名或密码错误'))
      }

      const expiredMessage = '登录已过期，请重新登录'
      ElMessage.error(expiredMessage)
      return Promise.reject(makeHandledError(expiredMessage, status))
    }

    ElMessage.error(message)
    return Promise.reject(makeHandledError(message, status))
  }
)

export default request
