import AES from './aes.js'
import { getToken, checkLogin, removeToken, setToken } from './auth'
import { login } from '../api'
import { getDomain, getEnvName } from './env'
import { cachedRequest, getCacheKey, clearCache } from './apiCache.js'

const API_PREFIX = '/api/app'

const config = {
  BASE_URL: getDomain() + API_PREFIX,
  API_PREFIX: API_PREFIX,
  DOMAIN: getDomain(),
  ENV_NAME: getEnvName(),
  TIMEOUT: 15000,
  LOGIN_PAGE: '/pages/login/login',
  CODE: {
    SUCCESS: 200,
    NEED_LOGIN: 1000,
    TOKEN_EXPIRED: 1001,
    TOKEN_INVALID: 1002
  },
  MAX_RETRY: 2
}

let isRefreshing = false
let refreshPromise = null

const isLoginPage = () => {
  try {
    const pages = getCurrentPages()
    const currentPage = pages[pages.length - 1]
    return currentPage?.route === 'pages/login/login'
  } catch (err) {
    return false
  }
}

const getCurrentPageInfo = () => {
  try {
    const pages = getCurrentPages()
    const currentPage = pages[pages.length - 1]
    return {
      route: currentPage?.route || 'unknown',
      options: currentPage?.options || {}
    }
  } catch (err) {
    return { route: 'unknown', options: {} }
  }
}

const refreshToken = async () => {
  if (isRefreshing) {
    return refreshPromise
  }

  const currentPage = getCurrentPageInfo()
  console.log(`📋 当前页面: ${currentPage.route}`)

  if (isLoginPage()) {
    console.log('⚠️ 当前在登录页，不执行自动刷新Token')
    return Promise.reject(new Error('当前在登录页'))
  }

  isRefreshing = true
  refreshPromise = new Promise(async (resolve, reject) => {
    try {
      console.log(`🔄 尝试自动刷新Token... (触发页面: ${currentPage.route})`)
      const loginRes = await uni.login()
      if (!loginRes.code) {
        throw new Error('获取微信code失败')
      }

      const tokenData = await login(loginRes.code)
      if (!tokenData?.token) {
        throw new Error('刷新Token失败')
      }

      setToken(tokenData.token)
      console.log(`✅ Token刷新成功 (触发页面: ${currentPage.route})`)
      resolve(tokenData.token)
    } catch (err) {
      console.error(`❌ Token刷新失败（触发页面: ${currentPage.route}）：`, err)
      removeToken()
      clearCache()
      reject(err)
    } finally {
      isRefreshing = false
      refreshPromise = null
    }
  })

  return refreshPromise
}

const executeRequest = async (options, retryCount = 0) => {
  const { url, data = {}, needLogin = true, showLoading = true, encrypt = true } = options

  if (showLoading) {
    uni.showLoading({ title: '处理中...', mask: true })
  }

  try {
    if (needLogin && url !== '/user/login' && !checkLogin()) {
      const currentPage = getCurrentPageInfo()
      console.log(`🔴 未登录检测 - 页面: ${currentPage.route}, 接口: ${url}`)
      if (retryCount === 0) {
        try {
          console.log(`🟡 准备调用 refreshToken - 页面: ${currentPage.route}`)
          await refreshToken()
          console.log(`🟢 refreshToken 成功，重试请求 - 页面: ${currentPage.route}`)
          return await executeRequest(options, retryCount + 1)
        } catch (err) {
          console.log(`🔴 refreshToken 失败: ${err.message} - 页面: ${currentPage.route}`)
          uni.showToast({ title: '请先登录', icon: 'none' })
          redirectToLogin()
          return Promise.reject(new Error('请先登录'))
        }
      }
      uni.showToast({ title: '请先登录', icon: 'none' })
      redirectToLogin()
      return Promise.reject(new Error('请先登录'))
    }

    const token = getToken()
    console.log(`🔵 [POST] 请求接口：${url}，参数：`, data)

    let requestData = {}
    if (encrypt) {
      requestData.data = await AES.encrypt(data)
    } else {
      requestData = data
    }

    const response = await new Promise((resolve, reject) => {
      const requestTask = uni.request({
        url: config.BASE_URL + url,
        method: 'POST',
        header: { token: token || '', 'Content-Type': 'application/json' },
        data: requestData,
        timeout: config.TIMEOUT,
        success: (res) => resolve(res),
        fail: (err) => reject(new Error(err.errMsg?.includes('timeout') ? '请求超时' : '网络异常'))
      })
      setTimeout(() => requestTask.abort(), config.TIMEOUT)
    })

    if (response.statusCode !== 200) {
      console.log(`🔵 [POST] 请求接口：${url}，Error：${response.statusCode}`)
      throw new Error(`请求出错啦 o(╥﹏╥)o`)
    }

    const encryptRes = response.data.data || ''
    let result = {}
    if (encrypt && encryptRes) {
      const decryptStr = await AES.decrypt(encryptRes)
      result = typeof decryptStr === 'string' ? JSON.parse(decryptStr) : decryptStr
    } else {
      result = response.data
    }
    console.log(`🟢 [POST] 请求接口：${url} 响应结果：`, result)

    if (result.code === config.CODE.SUCCESS) {
      return result.data ?? true
    } else if (result.code === config.CODE.NEED_LOGIN ||
               result.code === config.CODE.TOKEN_EXPIRED ||
               result.code === config.CODE.TOKEN_INVALID) {
      if (retryCount < config.MAX_RETRY) {
        console.log(`🔄 Token失效，尝试刷新（第${retryCount + 1}次）`)
        try {
          await refreshToken()
          return await executeRequest(options, retryCount + 1)
        } catch (err) {
          uni.showToast({ title: '登录已过期', icon: 'none' })
          removeToken()
          clearCache()
          setTimeout(() => redirectToLogin(), 1500)
          return Promise.reject(new Error('登录已过期'))
        }
      }
      uni.showToast({ title: '登录已过期', icon: 'none' })
      removeToken()
      clearCache()
      setTimeout(() => redirectToLogin(), 1500)
      return Promise.reject(new Error('登录已过期'))
    } else {
      throw new Error(result.msg || '请求失败')
    }

  } catch (err) {
    console.error(`🔴 [POST] 请求异常：`, err)
    if (err.message.includes('网络异常')) {
      uni.showToast({ title: '网络连接异常，请检查网络', icon: 'none', duration: 2000 })
    } else if (err.message.includes('请求超时')) {
      uni.showToast({ title: '请求超时，请稍后重试', icon: 'none', duration: 2000 })
    } else {
      uni.showToast({ title: err.message || '系统异常', icon: 'none', duration: 2000 })
    }
    return Promise.reject(err)
  } finally {
    if (showLoading) uni.hideLoading()
  }
}

const request = async (options, retryCount = 0) => {
  const { cache } = options

  if (cache === true && retryCount === 0) {
    const cacheKey = getCacheKey(options.url, options.data)
    return cachedRequest(cacheKey, () => executeRequest(options, retryCount), options.cacheTTL)
  }

  if (cache === 'bypass' && retryCount === 0) {
    const cacheKey = getCacheKey(options.url, options.data)
    clearCache(cacheKey)
  }

  return executeRequest(options, retryCount)
}

function redirectToLogin() {
  try {
    const pages = getCurrentPages()
    const currentPage = pages[pages.length - 1]
    if (currentPage?.route !== 'pages/login/login') {
      uni.redirectTo({ url: config.LOGIN_PAGE })
    }
  } catch (err) {
    uni.reLaunch({ url: config.LOGIN_PAGE })
  }
}

request.post = function (url, data = {}, options = {}) {
  return this({ url, data, ...options })
}

export const getRequestConfig = () => ({
  domain: config.DOMAIN,
  apiPrefix: config.API_PREFIX,
  baseUrl: config.BASE_URL,
  envName: config.ENV_NAME
})

export { clearCache }

export default request