import { joinApiUrl } from '@/config'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { useUserStore } from '@/store/user'

/** 是否正在处理 401 跳转，避免重复提示 */
export const isRelogin = { show: false }

const SESSION_EXPIRED_MSG = '登录过期，即将登录'
import { PAGE_LOGIN } from '@/utils/pageRoute'

const LOGIN_PAGE_URL = PAGE_LOGIN
const LOGIN_REDIRECT_DELAY_MS = 400

/** 与 ruoyi-ui tansParams 一致：null / undefined / 空字符串不参与序列化 */
function isEmptyParam(value) {
  return value === null || value === undefined || value === ''
}

/**
 * 剔除空值形参（GET 查询用）
 */
export function sanitizeParams(params) {
  if (params == null || typeof params !== 'object') {
    return params
  }
  if (Array.isArray(params)) {
    return params
  }
  const result = {}
  Object.keys(params).forEach((key) => {
    const value = params[key]
    if (isEmptyParam(value)) {
      return
    }
    if (typeof value === 'object' && !Array.isArray(value)) {
      const nested = sanitizeParams(value)
      if (nested && Object.keys(nested).length > 0) {
        result[key] = nested
      }
      return
    }
    result[key] = value
  })
  return result
}

function appendQuery(url, params) {
  const parts = []
  const build = (obj, prefix) => {
    Object.keys(obj).forEach((key) => {
      const value = obj[key]
      const name = prefix ? `${prefix}[${key}]` : key
      if (value !== null && value !== '' && typeof value !== 'undefined') {
        if (typeof value === 'object' && !Array.isArray(value)) {
          build(value, name)
        } else {
          parts.push(`${encodeURIComponent(name)}=${encodeURIComponent(value)}`)
        }
      }
    })
  }
  build(params, '')
  if (!parts.length) {
    return url
  }
  const qs = parts.join('&')
  return url + (url.indexOf('?') >= 0 ? '&' : '?') + qs
}

/**
 * 封装 uni.request，响应格式与 ruoyi-ui axios 拦截器一致
 */
export function request(options = {}) {
  const header = { ...(options.header || {}) }
  const skipToken = header.isToken === false
  delete header.isToken
  delete header.repeatSubmit
  if (skipToken) {
    delete header.Authorization
  } else if (getToken()) {
    header.Authorization = 'Bearer ' + getToken()
  }

  const method = (options.method || 'GET').toUpperCase()
  let url = (options.url || '').startsWith('http')
    ? options.url
    : joinApiUrl(options.url)

  let requestData = options.data !== undefined ? options.data : options.params

  if (method === 'GET' && requestData && typeof requestData === 'object' && !Array.isArray(requestData)) {
    const cleaned = sanitizeParams(requestData)
    const keys = Object.keys(cleaned || {})
    if (keys.length) {
      url = appendQuery(url, cleaned)
    }
    requestData = undefined
  }

  return new Promise((resolve, reject) => {
    uni.request({
      url,
      method,
      data: requestData,
      header: {
        'Content-Type': 'application/json;charset=utf-8',
        ...header
      },
      timeout: options.timeout || 10000,
      success: (res) => {
        const httpStatus = res.statusCode || 200
        const data = parseResponseData(res.data)
        const bizCode = data.code !== undefined && data.code !== null ? Number(data.code) : null
        const code = bizCode !== null && !Number.isNaN(bizCode) ? bizCode : httpStatus >= 200 && httpStatus < 300 ? 200 : httpStatus
        const msg = resolveErrorMessage(data, code)

        if (code === 401) {
          if (skipToken) {
            showErrorToast(msg)
            reject(new Error(msg))
          } else {
            handle401SessionExpired()
            reject(new Error(SESSION_EXPIRED_MSG))
          }
          return
        }
        if (code !== 200) {
          if (!options.silent) {
            showErrorToast(msg)
          }
          reject(new Error(msg || 'error'))
          return
        }
        resolve(data)
      },
      fail: (err) => {
        let message = err.errMsg || '网络异常'
        if (message.includes('timeout')) {
          message = '系统接口请求超时'
        } else if (message.includes('fail')) {
          message = '后端接口连接异常'
        }
        if (!options.silent) {
          showErrorToast(message)
        }
        reject(err)
      }
    })
  })
}

function parseResponseData(raw) {
  if (raw == null || raw === '') {
    return {}
  }
  if (typeof raw === 'object') {
    return raw
  }
  if (typeof raw === 'string') {
    try {
      return JSON.parse(raw)
    } catch (e) {
      return { msg: raw }
    }
  }
  return {}
}

function resolveErrorMessage(data, code) {
  const serverMsg = data && data.msg != null ? String(data.msg).trim() : ''
  if (serverMsg) {
    return serverMsg
  }
  const key = String(code)
  if (errorCode[key]) {
    return errorCode[key]
  }
  return errorCode.default || '请求失败'
}

function showErrorToast(message) {
  const title = (message && String(message).trim()) || errorCode.default || '请求失败'
  uni.showToast({
    title: title.length > 40 ? title.slice(0, 40) + '…' : title,
    icon: 'none',
    duration: 3000
  })
}

function handle401SessionExpired() {
  if (isRelogin.show) {
    return
  }
  isRelogin.show = true
  uni.showToast({
    title: SESSION_EXPIRED_MSG,
    icon: 'none',
    duration: 2000
  })
  setTimeout(() => {
    const userStore = useUserStore()
    userStore.fedLogOut().finally(() => {
      isRelogin.show = false
      uni.reLaunch({ url: LOGIN_PAGE_URL })
    })
  }, LOGIN_REDIRECT_DELAY_MS)
}

export default request
