import axios from 'axios'
import { ElMessage } from 'element-plus'
import router from '@/router'
import {getRefreshToken,refreshAccessToken} from "@/api/login.js";
import { baseUrl, acsBaseUrl, noAuthUrls as noAuthUrlList, requestTimeout, acsRequestTimeout, TOKEN_KEY, TOKEN_EXPIRE_KEY, USER_INFO_KEY } from '@/config/env.js'

// 检查URL是否需要认证
const urlNeedAuth = (url) => {
  return !noAuthUrlList.some(noAuthUrl => url.includes(noAuthUrl))
}

// 检查token是否过期
const isTokenExpired = () => {
  const token = localStorage.getItem(TOKEN_KEY)
  const expire = localStorage.getItem(TOKEN_EXPIRE_KEY)
  if (!token) return true
  
  // 检查过期时间
  if (expire) {
    const expireTime = parseInt(expire) * 1000 // 转换为毫秒
    const now = Date.now()
    return now >= expireTime
  }
  
  // 没有过期时间时，默认认为Token已过期（因为无法验证有效性）
  return true
}

// 检查token是否即将过期（5分钟内）
const isTokenExpiringSoon = () => {
  const expire = localStorage.getItem(TOKEN_EXPIRE_KEY)
  if (!expire) return false
  
  const expireTime = parseInt(expire) * 1000 // 转换为毫秒
  const now = Date.now()
  const fiveMinutes = 5 * 60 * 1000 // 5分钟
  
  // 如果已过期，返回false（由isTokenExpired处理）
  if (now >= expireTime) return false
  
  // 如果在5分钟内过期，返回true
  return (expireTime - now) <= fiveMinutes
}

// 正在刷新token的标志
let isRefreshing = false
// 等待刷新token的请求队列
let refreshSubscribers = []

// 添加请求到队列
const subscribeTokenRefresh = (callback) => {
  refreshSubscribers.push(callback)
}

// 刷新token后执行队列中的请求
const onTokenRefreshed = (newToken) => {
  refreshSubscribers.forEach(callback => callback(newToken))
  refreshSubscribers = []
}

// 执行token刷新
const doRefreshToken = async () => {
  try {
    const domain = window.location.hostname
    // 获取交换token
    const refreshTokenRes = await getRefreshToken(domain,{
      headers: {
        Authorization: `Bearer ${localStorage.getItem('token')}`
      }
    })
    
    if (refreshTokenRes.data?.code === 200 && refreshTokenRes.data?.data?.refresh_token) {
      // 使用交换token获取新的access token
      const newTokenRes = await refreshAccessToken(refreshTokenRes.data.data.refresh_token)
      
      if (newTokenRes.data?.code === 200 && newTokenRes.data?.data?.token) {
        const { token, expire } = newTokenRes.data.data
        localStorage.setItem(TOKEN_KEY, token)
        if (expire) {
          localStorage.setItem(TOKEN_EXPIRE_KEY, expire.toString())
        }
        return token
      }
    }
    // 刷新失败，触发登出逻辑
    localStorage.removeItem(TOKEN_KEY)
    localStorage.removeItem(TOKEN_EXPIRE_KEY)
    localStorage.removeItem(USER_INFO_KEY)
    ElMessage.warning('登录过期，请重新登录')
    router.push('/login')
    return null
  } catch (error) {
    console.error('Token刷新失败:', error)
    // 刷新失败，触发登出逻辑
    localStorage.removeItem(TOKEN_KEY)
    localStorage.removeItem(TOKEN_EXPIRE_KEY)
    localStorage.removeItem(USER_INFO_KEY)
    ElMessage.warning('登录过期，请重新登录')
    router.push('/login')
    return null
  }
}

class Request {
    constructor(config = {}) {
        // 创建 axios 实例
        this.instance = axios.create({
            baseURL: config.baseURL || '',
            timeout: config.timeout || 5000,
            headers: config.headers || {}
        })

        // 请求拦截器
        this.instance.interceptors.request.use(
            (config) => {
                // 在发送请求之前做些什么
                // 例如：添加 token
                const token = localStorage.getItem(TOKEN_KEY)
                if (token) {
                    config.headers.Authorization = `Bearer ${token}`
                }
                return config
            },
            (error) => {
                return Promise.reject(error)
            }
        )

        // 响应拦截器
        this.instance.interceptors.response.use(
            (response) => {
                // 对响应数据做点什么
                return response.data
            },
            (error) => {
                // 对响应错误做点什么
                // if (error.response) {
                //     switch (error.response.status) {
                //         case 401:
                //             // 未授权，可以在这里处理登出逻辑
                //             break
                //         case 403:
                //             // 禁止访问
                //             break
                //         case 404:
                //             // 未找到
                //             break
                //         case 500:
                //             // 服务器错误
                //             break
                //     }
                // }
                return error.response
            }
        )
    }

    // GET 请求
    get(url, params = {}, config = {}) {
        return this.instance.get(url, { params, ...config })
    }

    // POST 请求
    post(url, data = {}, config = {}) {
        return this.instance.post(url, data, config)
    }

    // PUT 请求
    put(url, data = {}, config = {}) {
        return this.instance.put(url, data, config)
    }

    // DELETE 请求
    delete(url, config = {}) {
        return this.instance.delete(url, config)
    }

    // PATCH 请求
    patch(url, data = {}, config = {}) {
        return this.instance.patch(url, data, config)
    }
}

// 创建默认实例
const request = new Request({
    baseURL: baseUrl,
    timeout: requestTimeout,
    headers: {
        'Content-Type': 'multipart/form-data'
    }
})

export const mainUrl = baseUrl + '/acs'
export const baseURL = baseUrl

export const http2 = axios.create({
    baseURL: baseUrl,
    timeout: acsRequestTimeout,
    headers: {},
});

http2.interceptors.request.use(async config => {
    const token = localStorage.getItem(TOKEN_KEY)
    
    // 检查是否需要认证
    if (urlNeedAuth(config.url)) {
        // 检查token是否已过期
        if (isTokenExpired()) {
            if (token) {
                localStorage.removeItem(TOKEN_KEY)
                localStorage.removeItem(TOKEN_EXPIRE_KEY)
                localStorage.removeItem(USER_INFO_KEY)
                ElMessage.warning('登录过期，请重新登录')
            }
            router.push('/login')
            return Promise.reject(new Error('Token已过期'))
        }
        
        // 检查token是否即将过期，进行无感刷新
        if (isTokenExpiringSoon() && !isRefreshing) {
            isRefreshing = true
            try {
                const newToken = await doRefreshToken()
                if (newToken) {
                    console.log('Token已无感刷新')
                    onTokenRefreshed(newToken)
                    config.headers.Authorization = `Bearer ${newToken}`
                } else {
                    // 刷新失败，doRefreshToken已处理登出逻辑，直接拒绝请求
                    return Promise.reject(new Error('Token刷新失败'))
                }
            } catch (error) {
                console.error('Token刷新异常:', error)
                // 刷新异常，doRefreshToken已处理登出逻辑，直接拒绝请求
                return Promise.reject(error)
            } finally {
                isRefreshing = false
            }
        } else if (isRefreshing) {
            // 正在刷新，等待刷新完成
            return new Promise((resolve, reject) => {
                subscribeTokenRefresh((newToken) => {
                    if (newToken) {
                        config.headers.Authorization = `Bearer ${newToken}`
                        // 重新发送原始请求
                        resolve(config)
                    } else {
                        reject(new Error('Token刷新失败'))
                    }
                })
            })
        } else {
            // 正常情况，直接使用token
            config.headers.Authorization = `Bearer ${token}`
        }
    }
    // 不需要认证的请求，不添加token
    
    return config
})

http2.interceptors.response.use(
    response => response, // 正常响应时直接返回
    error => {
        console.log('出现错误', error.response);
        if (error.response == undefined) {
            ElMessage.error("服务器错误，请稍后再试");
            return Promise.reject(error);
        }
        const { status } = error.response;
        if (status === 401) {
            localStorage.removeItem(TOKEN_KEY);
            ElMessage.warning('登陆过期，请重新登陆')
            router.push('/login')
            return Promise.reject();
        }
        // 其他错误处理（可选）
        return Promise.reject(error);
    }
);

export default request