/**
 * HTTP 客户端封装
 *
 * 基于 Axios 封装的 HTTP 请求模块，提供统一的请求/响应拦截、
 * Token 管理以及类型安全的请求方法。
 *
 * - baseURL 从 window.globalConfig.api.baseURL 读取，回退到 '/dev-api'
 * - 请求拦截器自动附加 Authorization Token
 * - 响应拦截器自动解包数据并统一错误提示
 *
 * @module utils/http
 */

import axios, {
  type AxiosInstance,
  type AxiosResponse,
  type AxiosRequestConfig,
  type InternalAxiosRequestConfig,
} from 'axios'
import { showFailToast } from 'vant'

// ══════════════════════════════════════════════
// 类型定义
// ══════════════════════════════════════════════

/** 后端统一响应结构 */
export interface ApiResponse<T = unknown> {
  /** 状态码，200 表示成功 */
  code: number
  /** 响应数据 */
  data: T
  /** 响应消息 */
  msg: string
}

// ══════════════════════════════════════════════
// Token 管理
// ══════════════════════════════════════════════

/** localStorage 中存储 Token 的键名 */
const TOKEN_KEY = 'Authorization'

/**
 * 获取本地存储的 Token
 * @returns Token 字符串，不存在时返回 null
 */
export function getToken(): string | null {
  return localStorage.getItem(TOKEN_KEY)
}

/**
 * 设置 Token 到本地存储
 * @param token - Token 字符串
 */
export function setToken(token: string): void {
  localStorage.setItem(TOKEN_KEY, token)
}

/**
 * 移除本地存储的 Token
 */
export function removeToken(): void {
  localStorage.removeItem(TOKEN_KEY)
}

// ══════════════════════════════════════════════
// Axios 实例
// ══════════════════════════════════════════════

/**
 * Axios 实例
 *
 * - baseURL：优先读取 window.globalConfig.api.baseURL，不存在时使用 '/dev-api'
 * - timeout：30 秒超时
 */
const http: AxiosInstance = axios.create({
  baseURL:
    (typeof window !== 'undefined' && window.globalConfig?.api?.baseURL) ||
    '/dev-api',
  timeout: 30_000,
})

// ══════════════════════════════════════════════
// 请求拦截器
// ══════════════════════════════════════════════

/**
 * 请求拦截器
 *
 * 在每次请求发出前，自动从 localStorage 读取 Token
 * 并附加到请求头的 Authorization 字段中。
 */
http.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    const token = getToken()
    if (token && config.headers) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  (error: unknown) => {
    return Promise.reject(error)
  },
)

// ══════════════════════════════════════════════
// 响应拦截器
// ══════════════════════════════════════════════

/**
 * 响应拦截器
 *
 * - 成功（code === 200）：解包返回 response.data.data
 * - 业务异常：弹出错误提示并 reject
 * - 网络异常：弹出错误提示并 reject
 */
http.interceptors.response.use(
  (response): AxiosResponse | Promise<AxiosResponse> => {
    const res = response.data as ApiResponse

    // 文件下载等特殊响应（非 JSON）直接返回
    if (response.config.responseType === 'blob') {
      return response
    }

    if (res.code === 200) {
      // 解包：将 response.data 替换为业务数据
      response.data = res.data
      return response
    }

    // 业务错误码处理
    const errMsg = res.msg || '请求失败'
    showFailToast(errMsg)

    // Token 过期等特殊错误码可在此扩展处理
    // if (res.code === 401) { removeToken(); /* 跳转登录 */ }

    return Promise.reject(new Error(errMsg))
  },
  (error: unknown) => {
    let msg = '网络错误，请稍后重试'

    if (axios.isAxiosError(error)) {
      const resData = error.response?.data as ApiResponse | undefined
      if (resData?.msg) {
        msg = resData.msg
      } else if (error.message) {
        msg = error.message
      }

      // HTTP 状态码特殊处理
      const status = error.response?.status
      if (status === 401) {
        msg = '登录已过期，请重新登录'
        removeToken()
        // TODO: 跳转登录页
      } else if (status === 403) {
        msg = '没有操作权限'
      } else if (status === 404) {
        msg = '请求的资源不存在'
      } else if (status === 500) {
        msg = '服务器内部错误'
      }
    } else if (error instanceof Error) {
      msg = error.message
    }

    showFailToast(msg)
    return Promise.reject(error)
  },
)

// ══════════════════════════════════════════════
// 类型安全的请求方法
// ══════════════════════════════════════════════

/**
 * GET 请求
 * @param url - 请求地址
 * @param params - 查询参数
 * @param config - Axios 请求配置
 * @returns Promise<T>
 */
export async function get<T>(
  url: string,
  params?: Record<string, unknown>,
  config?: AxiosRequestConfig,
): Promise<T> {
  return http.get(url, { params, ...config }) as Promise<T>
}

/**
 * POST 请求
 * @param url - 请求地址
 * @param data - 请求体数据
 * @param config - Axios 请求配置
 * @returns Promise<T>
 */
export async function post<T>(
  url: string,
  data?: unknown,
  config?: AxiosRequestConfig,
): Promise<T> {
  return http.post(url, data, config) as Promise<T>
}

/**
 * PUT 请求
 * @param url - 请求地址
 * @param data - 请求体数据
 * @param config - Axios 请求配置
 * @returns Promise<T>
 */
export async function put<T>(
  url: string,
  data?: unknown,
  config?: AxiosRequestConfig,
): Promise<T> {
  return http.put(url, data, config) as Promise<T>
}

/**
 * DELETE 请求
 * @param url - 请求地址
 * @param config - Axios 请求配置
 * @returns Promise<T>
 */
export async function del<T>(
  url: string,
  config?: AxiosRequestConfig,
): Promise<T> {
  return http.delete(url, config) as Promise<T>
}

/** 导出原始的 Axios 实例，供特殊场景（如文件上传进度监听）使用 */
export default http
