import axios, {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  InternalAxiosRequestConfig,
} from 'axios'
import { message } from 'antd'
import type { ApiResponse } from '../api/types'

/** 本地存储 token 的 key (存放后端返回的 accessToken) */
export const TOKEN_KEY = 'member_login_token'
/** 本地存储 userId 的 key (存放后端登录返回的 userId) */
export const USER_ID_KEY = 'member_login_user_id'
/** 本地存储 memberNo 的 key (后端登录返回的会员编号) */
export const MEMBER_NO_KEY = 'member_login_member_no'

/** 获取本地 token (accessToken) */
export const getToken = (): string => localStorage.getItem(TOKEN_KEY) || ''
/** 保存后端返回的 accessToken 到本地 */
export const setToken = (token: string): void => {
  localStorage.setItem(TOKEN_KEY, token)
}
/** 清除本地 token */
export const clearToken = (): void => {
  localStorage.removeItem(TOKEN_KEY)
  localStorage.removeItem(USER_ID_KEY)
  localStorage.removeItem(MEMBER_NO_KEY)
}

/** 获取本地 userId */
export const getUserId = (): string => localStorage.getItem(USER_ID_KEY) || ''
/** 保存后端返回的 userId 到本地 */
export const setUserId = (userId: string): void => {
  localStorage.setItem(USER_ID_KEY, userId)
}
/** 清除本地 userId */
export const clearUserId = (): void => {
  localStorage.removeItem(USER_ID_KEY)
}

/** 获取本地 memberNo (会员编号) */
export const getMemberNo = (): string =>
  localStorage.getItem(MEMBER_NO_KEY) || ''
/** 保存后端返回的 memberNo 到本地 */
export const setMemberNo = (memberNo: string): void => {
  localStorage.setItem(MEMBER_NO_KEY, memberNo)
}
/** 清除本地 memberNo */
export const clearMemberNo = (): void => {
  localStorage.removeItem(MEMBER_NO_KEY)
}

/** 创建 axios 实例 */
const service: AxiosInstance = axios.create({
  // 通过 Vite 代理转发到后端 / yapi mock
  // 实际拼接: /api + /v1/wechat/official-account/auth/login
  baseURL: '/api/v1/wechat/official-account',
  timeout: 15000,
  headers: {
    'Content-Type': 'application/json;charset=utf-8',
  },
})

// 请求拦截器: 自动携带 accessToken
// 从 localStorage 取出登录接口返回的 accessToken,放在 Authorization Bearer 头中
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    const token = getToken()
    if (token && config.headers) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  (error) => {
    console.error('[request error]', error)
    return Promise.reject(error)
  },
)

// 响应拦截器: 统一处理业务码
service.interceptors.response.use(
  (response: AxiosResponse<ApiResponse>) => {
    const res = response.data

    // 文件流等非标准响应直接放行
    if (response.config.responseType === 'blob') {
      return response as unknown as AxiosResponse<ApiResponse>
    }

    // 业务成功
    // 后端约定: success === true 表示调用成功, 业务数据在 data 中
    // 兼容部分接口只返回 code 0/200 的情况
    if (res.success === true || res.code === 0 || res.code === 200) {
      return response
    }

    // success === false 为业务失败
    if (res.success === false) {
      // 登录失效
      if (res.code === 401 || res.code === 403) {
        message.error(res.message || '登录已失效,请重新登录')
        clearToken()
        window.location.href = '/'
        return Promise.reject(new Error(res.message || 'Unauthorized'))
      }
      message.error(res.message || '请求失败')
      return Promise.reject(new Error(res.message || 'Error'))
    }

    // 登录失效
    if (res.code === 401 || res.code === 403) {
      message.error(res.message || '登录已失效,请重新登录')
      clearToken()
      // 跳转登录页(根据实际路由调整)
      window.location.href = '/'
      return Promise.reject(new Error(res.message || 'Unauthorized'))
    }

    // 其他业务错误
    message.error(res.message || '请求失败')
    return Promise.reject(new Error(res.message || 'Error'))
  },
  (error) => {
    // HTTP 错误处理
    let msg = '网络异常,请稍后重试'
    if (error.response) {
      const status = error.response.status
      switch (status) {
        case 400:
          msg = '请求参数错误'
          break
        case 401:
          msg = '未授权,请重新登录'
          clearToken()
          break
        case 403:
          msg = '拒绝访问'
          break
        case 404:
          msg = '请求地址不存在'
          break
        case 500:
          msg = '服务器内部错误'
          break
        case 502:
        case 503:
        case 504:
          msg = '服务暂不可用,请稍后重试'
          break
        default:
          msg = error.response.data?.message || `请求错误(${status})`
      }
    } else if (error.code === 'ECONNABORTED') {
      msg = '请求超时,请检查网络'
    }
    message.error(msg)
    return Promise.reject(error)
  },
)

/**
 * 通用请求方法
 * 自动剥离响应外层结构,直接返回 data 字段
 */
const request = <T = unknown>(config: AxiosRequestConfig): Promise<T> => {
  return service.request<ApiResponse<T>>(config).then((res) => res.data.data)
}

/** 便捷方法 */
request.get = <T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T> =>
  request<T>({ ...config, url, method: 'GET' })

request.post = <T = unknown>(
  url: string,
  data?: unknown,
  config?: AxiosRequestConfig,
): Promise<T> => request<T>({ ...config, url, method: 'POST', data })

request.put = <T = unknown>(
  url: string,
  data?: unknown,
  config?: AxiosRequestConfig,
): Promise<T> => request<T>({ ...config, url, method: 'PUT', data })

request.delete = <T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T> =>
  request<T>({ ...config, url, method: 'DELETE' })

export default request
export { service }
