import axios, { type AxiosInstance, type CreateAxiosDefaults, type AxiosRequestConfig } from 'axios'
import { tokenManager } from '@/lib/auth/token'
import { toast } from 'sonner'
import type { ApiResponse } from '@/types/api'
import { API_STATUS, ApiError } from '@/types/api'
import {
  type EncryptionConfig,
  DEFAULT_ENCRYPTION_CONFIG,
  encryptData,
  shouldEncryptRequest,
} from '@/lib/encryption/encryption'

// 扩展 AxiosRequestConfig 以支持 ignoreError 选项
export interface ExtendedAxiosRequestConfig extends AxiosRequestConfig {
  ignoreError?: boolean
}

// 扩展 AxiosInstance 类型以支持带有 ignoreError 的请求
export interface ExtendedAxiosInstance extends AxiosInstance {
  post<T = any, R = T, D = any>(
    url: string,
    data?: D,
    config?: ExtendedAxiosRequestConfig
  ): Promise<R>
  get<T = any, R = T>(url: string, config?: ExtendedAxiosRequestConfig): Promise<R>
  put<T = any, R = T, D = any>(
    url: string,
    data?: D,
    config?: ExtendedAxiosRequestConfig
  ): Promise<R>
  delete<T = any, R = T>(url: string, config?: ExtendedAxiosRequestConfig): Promise<R>
  patch<T = any, R = T, D = any>(
    url: string,
    data?: D,
    config?: ExtendedAxiosRequestConfig
  ): Promise<R>
}

export interface CreateHttpClientConfig extends CreateAxiosDefaults {
  serviceName: string
  baseURL?: string
  cookieString?: string // 用于服务端渲染时传递cookie
  showErrorToast?: boolean // 是否自动显示错误提示，默认为true
  encryption?: EncryptionConfig // 加密配置
}

const endpoints = {
  frog: process.env.NEXT_PUBLIC_FROG_API_URL,
  bear: process.env.NEXT_PUBLIC_BEAR_API_URL,
  lion: process.env.NEXT_PUBLIC_LION_API_URL,
  shark: process.env.NEXT_PUBLIC_SHARK_API_URL,
  cow: process.env.NEXT_PUBLIC_COW_API_URL,
  pigeon: process.env.NEXT_PUBLIC_PIGEON_API_URL,
}

export function createHttpClient(config: CreateHttpClientConfig): ExtendedAxiosInstance {
  const {
    serviceName,
    baseURL,
    cookieString,
    showErrorToast = true,
    encryption = DEFAULT_ENCRYPTION_CONFIG,
    ...axiosConfig
  } = config

  // 从环境变量获取服务地址，如果没有则使用默认地址
  const serviceBaseURL = endpoints[serviceName as keyof typeof endpoints] || baseURL

  const instance = axios.create({
    baseURL: serviceBaseURL,
    timeout: 120000,
    headers: {
      'Content-Type': 'application/json',
      Platform: 'web',
      Versionnum: '100',
    },
    ...axiosConfig,
  })

  // 请求拦截器
  instance.interceptors.request.use(
    (config) => {
      // 获取token - 支持服务端和客户端
      const token = tokenManager.getToken(cookieString)

      if (token) {
        // Java后端使用AUTH_TK字段接收token
        config.headers['AUTH_TK'] = token
      }

      config.headers['Accept-Language'] = 'en'

      // 获取设备ID - 支持服务端和客户端
      const deviceId = tokenManager.getDeviceId(cookieString)
      if (deviceId) {
        // Java后端使用AUTH_DID字段接收设备ID
        config.headers['AUTH_DID'] = deviceId
      }

      // 添加服务标识
      config.headers['X-Service'] = serviceName

      // 服务端渲染时，传递cookie
      if (typeof window === 'undefined' && cookieString) {
        config.headers.Cookie = cookieString
      }

      // 加密处理
      if (encryption.enabled && token && shouldEncryptRequest(config.data, encryption)) {
        try {
          console.log('config.data', config.data)
          // 加密请求数据
          const encryptedData = encryptData(config.data, token, encryption)
          config.data = encryptedData

          // // 添加加密标识头
          // config.headers[encryption.encryptHeader] = 'true'

          // 设置内容类型为JSON
          config.headers['Content-Type'] = 'application/json'
        } catch (error) {
          console.error('Request encryption failed:', error)
          // 加密失败时继续使用原始数据
        }
      }

      return config
    },
    (error) => {
      return Promise.reject(error)
    }
  )

  // 响应拦截器
  instance.interceptors.response.use(
    (response) => {
      const apiResponse = response.data as ApiResponse

      // 检查业务状态
      if (apiResponse.status === API_STATUS.OK) {
        // 成功：返回content内容
        return apiResponse.content
      } else {
        // 检查是否忽略错误
        const ignoreError = (response.config as ExtendedAxiosRequestConfig)?.ignoreError
        // 业务错误：创建ApiError并抛出
        const apiError = new ApiError(
          apiResponse.errorCode,
          apiResponse.errorMsg,
          apiResponse.traceId,
          !!ignoreError
        )

        // 错误提示由providers.tsx中的全局错误处理统一管理
        // 这里不再直接显示toast，避免重复弹窗

        return Promise.reject(apiError)
      }
    },
    (error) => {
      // 检查是否忽略错误
      const ignoreError = (error.config as ExtendedAxiosRequestConfig)?.ignoreError

      // 网络错误或其他HTTP错误
      let errorMessage = 'Network exception, please try again later'
      let errorCode = 'NETWORK_ERROR'

      // 创建标准化的错误对象
      const traceId = error.response?.headers?.['x-trace-id'] || 'unknown'
      const apiError = new ApiError(errorCode, errorMessage, traceId, !!ignoreError)

      return Promise.reject(apiError)
    }
  )

  return instance as ExtendedAxiosInstance
}
