// HTTP 请求封装
import { BASE_URL, REQUEST_TIMEOUT } from '../config'

interface RequestOptions {
  url: string
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE'
  data?: any
  params?: Record<string, any>
  header?: Record<string, string>
  loading?: boolean
}

interface ApiResponse<T = any> {
  code: number
  msg: string
  data: T
  timestamp: number
}

function translateErrorMsg(msg: string): string {
  if (msg.includes('Password mismatch')) return '密码错误'
  if (msg.includes('User not found') || msg.includes('Username does not exist')) return '用户不存在'
  if (msg.includes('Account disabled') || msg.includes('Account locked')) return '账号已被禁用'
  return msg
}

function getNetworkErrorMessage(err: any): string {
  // #ifdef H5
  if (typeof err === 'object') {
    // CORS / 预检失败常见表现
    if (err.status === 0 || err.readyState === 0) {
      return '无法连接服务器，请检查网络或后端地址配置（CORS/跨域）'
    }
  }
  // #endif

  const errMsg = String(err?.errMsg || err?.message || err || '')
  if (errMsg.includes('timeout') || errMsg.includes('超时')) {
    return '请求超时，请稍后重试'
  }
  if (errMsg.includes('fail') || errMsg.includes('无法连接') || errMsg.includes('connect')) {
    return '网络连接失败，请检查网络或服务器地址'
  }
  return '网络请求失败，请检查网络'
}

export async function request<T = any>(options: RequestOptions): Promise<T> {
  const { url, method = 'GET', data, params, header = {}, loading = true } = options

  if (loading) {
    uni.showLoading({ title: '加载中...', mask: true })
  }

  // 构建完整 URL
  let fullUrl = url.startsWith('http') ? url : `${BASE_URL}${url}`
  if (params) {
    const queryString = Object.entries(params)
      .filter(([, value]) => value !== undefined && value !== null)
      .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
      .join('&')
    if (queryString) {
      fullUrl += `${fullUrl.includes('?') ? '&' : '?'}${queryString}`
    }
  }

  // 获取 token
  const token = uni.getStorageSync('token')
  const requestHeader: Record<string, string> = {
    'Content-Type': 'application/json',
    ...header,
  }
  if (token) {
    requestHeader['Authorization'] = `Bearer ${token}`
  }

  return new Promise((resolve, reject) => {
    uni.request({
      url: fullUrl,
      method,
      data,
      header: requestHeader,
      timeout: REQUEST_TIMEOUT,
      success: (res) => {
        if (loading) uni.hideLoading()

        const payload = res.data as any

        if (res.statusCode === 200) {
          // R 包装：{ code, msg, data }
          if (payload && typeof payload.code === 'number') {
            if (payload.code === 200) {
              resolve(payload.data)
            } else {
              uni.showToast({ title: translateErrorMsg(payload.msg) || '请求失败', icon: 'none' })
              reject(new Error(translateErrorMsg(payload.msg)))
            }
          } else if (payload && Array.isArray(payload.rows) && typeof payload.total === 'number') {
            // 裸 PageResult（如客户列表直接返回分页对象）
            resolve(payload as T)
          } else {
            // 其他直接返回的数据
            resolve(payload as T)
          }
        } else if (res.statusCode === 401) {
          uni.showToast({ title: '登录已过期，请重新登录', icon: 'none' })
          uni.removeStorageSync('token')
          uni.removeStorageSync('user')
          uni.reLaunch({ url: '/pages/login/login' })
          reject(new Error('Unauthorized'))
        } else if (res.statusCode === 0 || res.statusCode === undefined) {
          // 部分平台网络异常时 statusCode 为 0
          const msg = getNetworkErrorMessage(res)
          uni.showToast({ title: msg, icon: 'none' })
          reject(new Error(msg))
        } else {
          uni.showToast({ title: `请求失败 (${res.statusCode})`, icon: 'none' })
          reject(new Error(`HTTP ${res.statusCode}`))
        }
      },
      fail: (err) => {
        if (loading) uni.hideLoading()
        const msg = getNetworkErrorMessage(err)
        uni.showToast({ title: msg, icon: 'none' })
        reject(new Error(msg))
      },
    })
  })
}

// 便捷方法
export function get<T = any>(url: string, params?: Record<string, any>, options?: Partial<RequestOptions>) {
  return request<T>({ url, method: 'GET', params, ...options })
}

export function post<T = any>(url: string, data?: any, options?: Partial<RequestOptions>) {
  return request<T>({ url, method: 'POST', data, ...options })
}

export function put<T = any>(url: string, data?: any, options?: Partial<RequestOptions>) {
  return request<T>({ url, method: 'PUT', data, ...options })
}

export function del<T = any>(url: string, params?: Record<string, any>, options?: Partial<RequestOptions>) {
  return request<T>({ url, method: 'DELETE', params, ...options })
}
