/**
 * HTTP请求工具
 * 基于axios封装的统一请求实例
 */

import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios'
import { ElMessage, ElMessageBox } from 'element-plus'
import { envConfig } from '@/config/env'

// 请求响应接口
export interface ApiResponse<T = any> {
  code: number
  message: string
  data: T
  success: boolean
  timestamp: number
}

// 请求配置接口
export interface RequestConfig extends AxiosRequestConfig {
  // 是否显示loading
  showLoading?: boolean
  // 是否显示错误消息
  showError?: boolean
  // 是否需要token
  needToken?: boolean
}

// 创建axios实例
const createAxiosInstance = (): AxiosInstance => {
  const instance = axios.create({
    baseURL: envConfig.apiBaseUrl,
    timeout: 30000,
    headers: {
      'Content-Type': 'application/json;charset=UTF-8'
    }
  })

  // 请求拦截器
  instance.interceptors.request.use(
    (config: any) => {
      // 添加token
      const token = localStorage.getItem('access_token')
      console.log('🔑 请求拦截器 - Token状态:', {
        hasToken: !!token,
        tokenPreview: token ? `${token.substring(0, 20)}...` : 'null',
        url: config.url,
        needToken: config.needToken
      })

      if (token && config.needToken !== false) {
        config.headers.Authorization = `Bearer ${token}`
        console.log('🔑 已添加Authorization头')
      } else {
        console.log('🔑 未添加Authorization头 - 原因:', !token ? '无token' : 'needToken=false')
      }

      // 添加请求ID用于追踪
      config.headers['X-Request-ID'] = generateRequestId()

      // 打印请求日志
      if (envConfig.debug) {
        console.log('🚀 Request:', {
          url: config.url,
          method: config.method,
          params: config.params,
          data: config.data,
          headers: config.headers
        })
      }

      return config
    },
    (error: AxiosError) => {
      console.error('❌ Request Error:', error)
      return Promise.reject(error)
    }
  )

  // 响应拦截器
  instance.interceptors.response.use(
    (response: AxiosResponse<ApiResponse>) => {
      const { data } = response
      
      // 打印响应日志
      if (envConfig.debug) {
        console.log('✅ Response:', {
          url: response.config.url,
          status: response.status,
          data: data
        })
      }

      // 检查业务状态码
      if (data.code === 200 || data.success) {
        return data
      }

      // 处理业务错误
      const errorMessage = data.message || '请求失败'
      
      // 特殊错误码处理
      switch (data.code) {
        case 401:
          console.warn('🚫 业务层401错误:', errorMessage)
          // 只有在非登录接口时才处理401
          if (!response.config.url?.includes('/auth/login')) {
            handleUnauthorized()
          } else {
            ElMessage.error(errorMessage)
          }
          break
        case 403:
          ElMessage.error('没有权限访问该资源')
          break
        case 404:
          ElMessage.error('请求的资源不存在')
          break
        case 500:
          ElMessage.error('服务器内部错误')
          break
        default:
          ElMessage.error(errorMessage)
      }

      return Promise.reject(new Error(errorMessage))
    },
    (error: AxiosError) => {
      console.error('❌ Response Error:', error)

      let errorMessage = '网络请求失败'

      if (error.response) {
        // 服务器响应错误
        const { status, data } = error.response
        
        switch (status) {
          case 400:
            errorMessage = '请求参数错误'
            break
          case 401:
            errorMessage = '未授权，请重新登录'
            console.warn('🚫 HTTP层401错误')
            // 只有在非登录接口时才处理401
            if (!error.config?.url?.includes('/auth/login')) {
              handleUnauthorized()
            }
            break
          case 403:
            errorMessage = '拒绝访问'
            break
          case 404:
            errorMessage = '请求地址不存在'
            break
          case 408:
            errorMessage = '请求超时'
            break
          case 500:
            errorMessage = '服务器内部错误'
            break
          case 502:
            errorMessage = '网关错误'
            break
          case 503:
            errorMessage = '服务不可用'
            break
          case 504:
            errorMessage = '网关超时'
            break
          default:
            errorMessage = (data as any)?.message || `请求失败 (${status})`
        }
      } else if (error.request) {
        // 网络错误
        errorMessage = '网络连接失败，请检查网络'
      } else {
        // 其他错误
        errorMessage = error.message || '请求配置错误'
      }

      ElMessage.error(errorMessage)
      return Promise.reject(error)
    }
  )

  return instance
}

// 处理未授权
const handleUnauthorized = () => {
  console.warn('🚫 收到401未授权响应')

  // 计算当前应用登录页路径，兼容本地和生产环境
  const base = import.meta.env.BASE_URL || '/'
  const normalizedBase = base.endsWith('/') ? base : `${base}/`
  const loginPath = `${normalizedBase}login`

  // 如果已经在登录页，避免重复处理
  if (window.location.pathname === loginPath) {
    console.log('🚫 当前在登录页面，不处理401错误')
    return
  }

  // 不立即清除认证信息，而是提示用户
  ElMessageBox.confirm(
    '登录状态已过期，请重新登录',
    '提示',
    {
      confirmButtonText: '重新登录',
      cancelButtonText: '取消',
      type: 'warning'
    }
  ).then(() => {
    // 用户确认后才清除认证信息
    localStorage.removeItem('access_token')
    localStorage.removeItem('refresh_token')
    localStorage.removeItem('user_info')

    // 使用带前缀的完整登录路径，避免 404
    window.location.href = loginPath
  }).catch(() => {
    // 用户取消，不清除认证信息，让用户继续操作
    console.log('🚫 用户取消重新登录')
  })
}

// 生成请求ID
const generateRequestId = (): string => {
  return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`
}

// 创建请求实例
export const request = createAxiosInstance()

// 导出请求方法
export const http = {
  get: <T = any>(url: string, config?: RequestConfig) => 
    request.get<any, ApiResponse<T>>(url, config),
  
  post: <T = any>(url: string, data?: any, config?: RequestConfig) => 
    request.post<any, ApiResponse<T>>(url, data, config),
  
  put: <T = any>(url: string, data?: any, config?: RequestConfig) => 
    request.put<any, ApiResponse<T>>(url, data, config),
  
  delete: <T = any>(url: string, config?: RequestConfig) => 
    request.delete<any, ApiResponse<T>>(url, config),
  
  patch: <T = any>(url: string, data?: any, config?: RequestConfig) => 
    request.patch<any, ApiResponse<T>>(url, data, config)
}

export default request
