import axios, { InternalAxiosRequestConfig, AxiosRequestConfig, AxiosResponse } from 'axios'
import { ElMessage } from 'element-plus'
import { useUserStore } from '@/store/modules/user'
import { ApiStatus } from './status'
import type { RequestOptions, ErrorMessageMode } from '@/types/api'

const axiosInstance = axios.create({
  timeout: 15000, // 请求超时时间(毫秒)
  baseURL: import.meta.env.DEV ? '' : import.meta.env.VITE_API_URL, // 开发服务器使用代理，其他模式使用完整URL
  withCredentials: false, // 异步请求携带cookie
  transformRequest: [
    (data) => {
      // 如果是 FormData,不进行转换
      if (data instanceof FormData) {
        return data
      }
      // 其他数据转换为 JSON 字符串
      return JSON.stringify(data)
    }
  ],
  validateStatus: (status) => status >= 200 && status < 300, // 只接受 2xx 的状态码
  headers: {
    get: { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8' },
    post: { 'Content-Type': 'application/json;charset=utf-8' }
  },
  transformResponse: [
    (data, headers) => {
      const contentType = headers['content-type']
      if (contentType && contentType.includes('application/json')) {
        try {
          return JSON.parse(data)
        } catch {
          return data
        }
      }
      return data
    }
  ]
})

// 请求拦截器
axiosInstance.interceptors.request.use(
  (request: InternalAxiosRequestConfig) => {
    const { accessToken } = useUserStore()

    // 如果 token 存在，则设置请求头
    if (accessToken) {
      // 如果是 FormData,不要覆盖 Content-Type (让浏览器自动设置 boundary)
      if (request.data instanceof FormData) {
        request.headers.set('Authorization', `Bearer ${accessToken}`)
        // 删除 Content-Type,让浏览器自动设置
        delete request.headers['Content-Type']
      } else {
        request.headers.set({
          'Content-Type': 'application/json',
          Authorization: `Bearer ${accessToken}`
        })
      }
    }

    return request // 返回修改后的配置
  },
  (error) => {
    ElMessage.error('服务器异常！') // 显示错误消息
    return Promise.reject(error) // 返回拒绝的 Promise
  }
)

// Token 刷新相关
let isRefreshing = false // 是否正在刷新 token
let failedQueue: Array<{
  resolve: (value?: any) => void
  reject: (reason?: any) => void
}> = [] // 失败队列，存储因 token 过期而失败的请求
let isHandlingAuthExpiry = false

// 处理失败队列
const processQueue = (error: any, token: string | null = null) => {
  failedQueue.forEach((prom) => {
    if (error) {
      prom.reject(error)
    } else {
      prom.resolve(token)
    }
  })
  failedQueue = []
}

// 响应拦截器
axiosInstance.interceptors.response.use(
  (response: AxiosResponse) => {
    // 401 未授权 - 尝试刷新 token
    if (response.data.code === ApiStatus.unauthorized) {
      const userStore = useUserStore()
      const originalRequest = response.config as any

      // 如果没有 refreshToken，直接清理本地状态（不调用退出接口）
      if (!userStore.refreshToken) {
        clearLocalStateAndRedirect()
        return Promise.reject(response)
      }

      // 如果正在刷新 token，将请求加入队列
      if (isRefreshing) {
        return new Promise((resolve, reject) => {
          failedQueue.push({ resolve, reject })
        })
          .then((token) => {
            originalRequest.headers['Authorization'] = `Bearer ${token}`
            return axiosInstance.request(originalRequest)
          })
          .catch((err) => {
            return Promise.reject(err)
          })
      }

      // 标记正在刷新
      originalRequest._retry = true
      isRefreshing = true

      // 调用刷新 token 接口
      return new Promise((resolve, reject) => {
        axiosInstance
          .post('/api/auth/refresh', { refreshToken: userStore.refreshToken })
          .then((res) => {
            const { data } = res

            // 刷新成功
            if (data.code === ApiStatus.success && data.data?.access_token) {
              // 更新 token
              userStore.setToken(data.data.access_token, data.data.refresh_token)

              // 更新请求头
              originalRequest.headers['Authorization'] = `Bearer ${data.data.access_token}`
              axiosInstance.defaults.headers.common['Authorization'] =
                `Bearer ${data.data.access_token}`

              // 处理队列中的请求
              processQueue(null, data.data.access_token)

              // 重试原请求
              resolve(axiosInstance.request(originalRequest))
            } else {
              // 刷新失败 - 清理本地状态（不调用退出接口）
              processQueue(new Error('Token refresh failed'), null)
              clearLocalStateAndRedirect()
              reject(res)
            }
          })
          .catch((err) => {
            // 刷新失败 - 清理本地状态（不调用退出接口）
            processQueue(err, null)
            clearLocalStateAndRedirect()
            reject(err)
          })
          .finally(() => {
            isRefreshing = false
          })
      })
    }
    return response
  },
  (error) => {
    if (axios.isCancel(error)) {
      console.log('repeated request: ' + error.message)
      return Promise.reject(error)
    }

    // 处理 HTTP 401 状态码 - 直接清理本地状态（不调用退出接口）
    if (error.response && error.response.status === 401) {
      console.warn('HTTP 401 Unauthorized - 强制退出登录')
      clearLocalStateAndRedirect()
      return Promise.reject(error)
    }

    // 注意：错误处理现在在request函数中根据requestOptions处理
    return Promise.reject(error)
  }
)

// 扩展的请求配置接口
interface ExtendedRequestConfig extends AxiosRequestConfig {
  requestOptions?: RequestOptions
}

// 处理请求配置
function processRequestConfig(config: ExtendedRequestConfig): AxiosRequestConfig {
  const { requestOptions, ...axiosConfig } = config

  // 应用自定义请求选项
  if (requestOptions) {
    // 处理是否携带token
    if (requestOptions.withToken === false) {
      axiosConfig.headers = { ...axiosConfig.headers }
      delete axiosConfig.headers?.Authorization
    }

    // 处理是否添加时间戳
    if (requestOptions.joinTime) {
      const timestamp = Date.now()
      if (axiosConfig.method?.toUpperCase() === 'GET') {
        axiosConfig.params = { ...axiosConfig.params, _t: timestamp }
      }
    }

    // 处理API URL
    if (requestOptions.apiUrl) {
      axiosConfig.baseURL = requestOptions.apiUrl
    }
  }

  return axiosConfig
}

// 处理错误消息
function handleErrorMessage(
  error: any,
  mode: ErrorMessageMode = 'message',
  show404Error: boolean = true
) {
  if (mode === 'none') return

  const backendMessage = error.response?.data?.msg
  const httpStatus = error.response?.status

  // 401 过期类错误由 clearLocalStateAndRedirect 统一提示，避免重复弹出后端报错。
  if (httpStatus === 401 || error.response?.data?.code === ApiStatus.unauthorized) {
    return
  }

  // 如果是404错误，且未配置显示404错误，则不显示任何提示
  if (httpStatus === 404 && !show404Error) {
    return
  }

  // 如果后端返回了错误信息，使用后端信息
  if (backendMessage) {
    if (mode === 'modal') {
      // TODO: 可以使用 ElMessageBox 显示模态框
      ElMessage.error(backendMessage)
    } else {
      ElMessage.error(backendMessage)
    }
    return
  }

  // 其他错误显示通用提示
  const message = '请求超时或服务器异常！'
  if (mode === 'modal') {
    // TODO: 可以使用 ElMessageBox 显示模态框
    ElMessage.error(message)
  } else {
    ElMessage.error(message)
  }
}

// 请求
async function request<T = any>(config: ExtendedRequestConfig): Promise<T> {
  const processedConfig = processRequestConfig(config)

  // 对 POST | PUT | PATCH 请求特殊处理
  if (
    processedConfig.method?.toUpperCase() === 'POST' ||
    processedConfig.method?.toUpperCase() === 'PUT' ||
    processedConfig.method?.toUpperCase() === 'PATCH'
  ) {
    // 如果已经有 data，则保留原有的 data
    if (processedConfig.params && !processedConfig.data) {
      processedConfig.data = processedConfig.params
      processedConfig.params = undefined // 使用 undefined 而不是空对象
    }
  }

  try {
    const res = await axiosInstance.request<T>(processedConfig)
    return res.data
  } catch (e) {
    if (axios.isAxiosError(e)) {
      // 默认显示错误消息，除非明确设置为 'none'
      const errorMode = config.requestOptions?.errorMessageMode || 'message'
      const show404Error =
        config.requestOptions?.show404Error !== undefined
          ? config.requestOptions.show404Error
          : true
      handleErrorMessage(e, errorMode, show404Error)
    }
    return Promise.reject(e)
  }
}

// API 方法集合
const api = {
  get<T>(config: ExtendedRequestConfig): Promise<T> {
    return request({ ...config, method: 'GET' }) // GET 请求
  },
  post<T>(config: ExtendedRequestConfig): Promise<T> {
    return request({ ...config, method: 'POST' }) // POST 请求
  },
  put<T>(config: ExtendedRequestConfig): Promise<T> {
    return request({ ...config, method: 'PUT' }) // PUT 请求
  },
  patch<T>(config: ExtendedRequestConfig): Promise<T> {
    return request({ ...config, method: 'PATCH' }) // PATCH 请求
  },
  del<T>(config: ExtendedRequestConfig): Promise<T> {
    return request({ ...config, method: 'DELETE' }) // DELETE 请求
  },
  request<T>(config: ExtendedRequestConfig): Promise<T> {
    return request({ ...config }) // 通用请求
  }
}

// 仅清理本地状态（不调用接口）- 用于401等情况
const clearLocalStateAndRedirect = () => {
  if (isHandlingAuthExpiry) return
  isHandlingAuthExpiry = true

  ElMessage.error('登录已过期，请重新登录')
  setTimeout(() => {
    useUserStore().clearLocalState()
    isHandlingAuthExpiry = false
  }, 1000)
}

export default api
