import axios from 'axios'
import type { InternalAxiosRequestConfig } from 'axios'
import { getRequestLang } from '@/utils/backendLang'

const request = axios.create({
  baseURL: import.meta.env.VITE_API_BASE,
  timeout: 15000,
})

// 与 router 中 meta.requiresAuth: true 的路由前缀保持一致
const AUTH_REQUIRED_PREFIXES = ['/account', '/assets', '/invite', '/finance']

function isOnAuthRequiredPage(): boolean {
  const path = window.location.pathname
  return AUTH_REQUIRED_PREFIXES.some((p) => path === p || path.startsWith(p + '/'))
}

// ── 会话失效回调（由 App.vue 注册，触发 auth store 清除本地状态）────────
let _onSessionExpired: (() => void) | null = null
export function registerSessionExpiredHandler(fn: () => void) {
  _onSessionExpired = fn
}

// 防止并发请求重复触发登出
let _sessionInvalidHandled = false

// 与 Flutter dio_client 一致：仅 4000（token 过期）触发登出
// 10006 = "用户未登录" — 公开接口对未登录用户正常返回，不应触发登出
const SESSION_INVALID_CODES = new Set([4000])

function handleSessionInvalid(source: string) {
  if (_sessionInvalidHandled) return
  if (!localStorage.getItem('token')) return
  // 方便定位是哪个接口触发了登出：打开 DevTools → Console 查看
  console.warn('[AUTH] session invalid triggered by:', source)
  _sessionInvalidHandled = true
  localStorage.removeItem('token')
  _onSessionExpired?.()
  if (isOnAuthRequiredPage()) {
    window.location.href = '/login'
  }
}

// 登录成功后重置，让下次会话失效可以正常触发
export function resetSessionInvalidFlag() {
  _sessionInvalidHandled = false
}

// ── 请求拦截：注入 token 和必要的客户端头（后端依赖 lang 做本地化）────────
request.interceptors.request.use((config: InternalAxiosRequestConfig) => {
  const token = localStorage.getItem('token')
  if (token) {
    config.headers['x-auth-token'] = token
    ;(config as any)._hadToken = true
  }
  config.headers['lang'] = getRequestLang()
  return config
})

// ── 响应拦截：统一处理业务错误 ───────────────────────────────
// 部分接口（market/*）直接返回裸数据（数组或无 code 字段的对象），
// 业务接口（uc/*、swap/*）返回 { code: 0, message, data }。
request.interceptors.response.use(
  (response) => {
    const data = response.data
    if (data !== null && typeof data === 'object' && !Array.isArray(data) && 'code' in data) {
      const code = (data as { code: unknown }).code
      const ok = code === 0 || code === '0'
      if (!ok) {
        const codeNum = typeof code === 'number' ? code : Number(code)
        const hadToken = !!(response.config as any)._hadToken
        if (SESSION_INVALID_CODES.has(codeNum) && hadToken) {
          handleSessionInvalid(`${response.config.url} → code ${codeNum}`)
        }
        return Promise.reject(new Error(data.message || data.msg || `请求失败（${data.code}）`))
      }
      return data.data !== undefined ? data.data : data
    }
    return data
  },
  (error) => {
    const hadToken = !!(error.config as any)?._hadToken
    if (error.response?.status === 401 && hadToken) {
      handleSessionInvalid(`${error.config?.url} → HTTP 401`)
    }
    return Promise.reject(
      new Error(error.response?.data?.message || error.response?.data?.msg || '网络异常，请稍后重试'),
    )
  },
)

export default request

// ── JSON 请求 ─────────────────────────────────────────────
export const get  = <T>(url: string, params?: object) => request.get<never, T>(url, { params })
export const post = <T>(url: string, data?: object)  => request.post<never, T>(url, data)
export const put   = <T>(url: string, data?: object) => request.put<never, T>(url, data)
export const patch = <T>(url: string, data?: object) => request.patch<never, T>(url, data)
export const del  = <T>(url: string)                 => request.delete<never, T>(url)

// ── form-data 请求（实际后端大多数接口使用 form-data）────────
export const postForm = <T>(url: string, data?: Record<string, string | number | undefined>) => {
  const params = new URLSearchParams()
  if (data) {
    for (const [key, val] of Object.entries(data)) {
      if (val !== undefined && val !== null) {
        params.append(key, String(val))
      }
    }
  }
  return request.post<never, T>(url, params)
}
