import axios, { type AxiosResponse, type InternalAxiosRequestConfig, type Method } from 'axios'
import { ElMessage } from 'element-plus'
import router from '@/router'
import type { ApiResponse } from '@/types'

// 部署base路径，用于token过期时跳转登录页
const routerBase = import.meta.env.BASE_URL

// 创建axios实例
const service = axios.create({
  timeout: 30000,
})

// 请求拦截器
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    // 根据当前路由判断是否为Mock模式
    const isMock = window.location.pathname.startsWith('/mock')
    config.baseURL = isMock ? '/mock-api' : '/api'

    // 自动添加Token
    const token = localStorage.getItem('token')
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  (error) => Promise.reject(error)
)

// 响应拦截器：解包 AxiosResponse → ApiResponse
service.interceptors.response.use(
  (response: AxiosResponse): any => {
    const res = response.data as ApiResponse
    if (res.code === 0) {
      return res
    }

    // Token无效/过期
    if (res.code === 40101) {
      localStorage.removeItem('token')
      const loginPath = routerBase + 'login'
      router.push(loginPath)
      ElMessage.warning('登录已过期')
      return Promise.reject(new Error(res.message))
    }

    // 其他业务错误：优先显示后端返回的消息，便于定位问题
    const msg = res.message || '请求失败'
    ElMessage.error(msg)
    return Promise.reject(new Error(msg))
  },
  (error) => {
    // HTTP 错误（4xx/5xx）：尝试解析后端返回的错误信息
    if (error.response) {
      const data = error.response.data as ApiResponse | undefined
      const msg = data?.message || `请求失败 (${error.response.status})`
      ElMessage.error(msg)
    } else if (error.code === 'ECONNABORTED') {
      ElMessage.error('请求超时')
    } else {
      ElMessage.error('网络异常，请检查网络连接')
    }
    return Promise.reject(error)
  }
)

/**
 * 类型安全的请求封装
 * 响应拦截器已将 AxiosResponse 解包为 ApiResponse<T>
 * 调用方拿到的就是 ApiResponse<T>，可直接访问 .data / .code / .message
 */
const request = {
  get<T = unknown>(url: string, config?: object): Promise<ApiResponse<T>> {
    return service.get(url, config) as unknown as Promise<ApiResponse<T>>
  },
  post<T = unknown>(url: string, data?: unknown, config?: object): Promise<ApiResponse<T>> {
    return service.post(url, data, config) as unknown as Promise<ApiResponse<T>>
  },
  put<T = unknown>(url: string, data?: unknown, config?: object): Promise<ApiResponse<T>> {
    return service.put(url, data, config) as unknown as Promise<ApiResponse<T>>
  },
  delete<T = unknown>(url: string, config?: object): Promise<ApiResponse<T>> {
    return service.delete(url, config) as unknown as Promise<ApiResponse<T>>
  },
}

export default request
