import axios, {
  type AxiosError,
  type AxiosInstance,
  type AxiosRequestConfig,
  type AxiosResponse,
  type InternalAxiosRequestConfig,
} from "axios"

// 定义通用的 API 响应接口
interface ApiResponse<T = any> {
  data: T
  code: number
  msg: string
}

// 扩展 Axios 请求配置
interface RequestConfig extends AxiosRequestConfig {
  timeout?: number
  headers?: Record<string, string>
}

// 定义可能的错误类型
type HttpClientError = AxiosError | Error

class ServerHttpClient {
  private instance: AxiosInstance

  constructor() {
    // 创建axios实例
    this.instance = axios.create({
      baseURL: process.env.NEXT_PUBLIC_API_BASE ?? "http://localhost:8080",
      timeout: 10000,
      headers: {
        "Content-Type": "application/json",
      },
    })

    this.setupRequestInterceptors()
    this.setupResponseInterceptors()
  }

  private setupRequestInterceptors() {
    this.instance.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        return config
      },
      (error: any) => {
        return Promise.reject(error)
      },
    )
  }

  private setupResponseInterceptors() {
    this.instance.interceptors.response.use(
      (response: AxiosResponse<ApiResponse<any>>) => {
        return response
      },
      (error: AxiosError) => {
        // 服务端只返回错误，不做 UI 提示
        return Promise.reject(error)
      },
    )
  }

  // GET 请求
  async serverGet<TResponse = any, TParams extends Record<string, any> | null = Record<string, any> | null>(
    url: string,
    params?: TParams,
    config?: RequestConfig & { arrayFormat?: "indices" | "repeat" | "comma" },
  ): Promise<ApiResponse<TResponse>> {
    try {
      const response = await this.instance.get<ApiResponse<TResponse>>(url, {
        params,
        paramsSerializer: (p) => {
          const parts: string[] = []
          for (const key in p) {
            const value = (p as any)[key]
            if (Array.isArray(value)) {
              switch (config?.arrayFormat ?? "indices") {
                case "repeat":
                  value.forEach((v) => parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(v)}`))
                  break
                case "comma":
                  parts.push(`${encodeURIComponent(key)}=${value.map((v) => encodeURIComponent(v)).join(",")}`)
                  break
                case "indices":
                default:
                  value.forEach((v, i) => parts.push(`${encodeURIComponent(key)}[${i}]=${encodeURIComponent(v)}`))
                  break
              }
            } else if (value !== undefined && value !== null) {
              parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
            }
          }
          return parts.join("&")
        },
        ...config,
      })
      return response.data
    } catch (error: any) {
      throw this.handleError(error)
    }
  }

  // POST 请求
  async serverPost<TResponse = any, TData extends Record<string, any> | null = Record<string, any> | null>(
    url: string,
    data?: TData,
    config?: RequestConfig,
  ): Promise<ApiResponse<TResponse>> {
    try {
      const response = await this.instance.post<ApiResponse<TResponse>>(url, JSON.stringify(data), config)
      return response.data
    } catch (error: any) {
      throw this.handleError(error)
    }
  }

  // PUT 请求
  async serverPut<TResponse = any, TData extends Record<string, any> | null = Record<string, any> | null>(
    url: string,
    data?: TData,
    config?: RequestConfig,
  ): Promise<ApiResponse<TResponse>> {
    try {
      const response = await this.instance.put<ApiResponse<TResponse>>(url, JSON.stringify(data), config)
      return response.data
    } catch (error: any) {
      throw this.handleError(error)
    }
  }

  // DELETE 请求
  async serverDelete<TResponse = any, TParams extends Record<string, any> | null = Record<string, any> | null>(
    url: string,
    params?: TParams,
    config?: RequestConfig & { arrayFormat?: "indices" | "repeat" | "comma" },
  ): Promise<ApiResponse<TResponse>> {
    try {
      const response = await this.instance.delete<ApiResponse<TResponse>>(url, {
        params,
        paramsSerializer: (p) => {
          const parts: string[] = []
          for (const key in p) {
            const value = (p as any)[key]
            if (Array.isArray(value)) {
              switch (config?.arrayFormat ?? "indices") {
                case "repeat":
                  value.forEach((v) => parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(v)}`))
                  break
                case "comma":
                  parts.push(`${encodeURIComponent(key)}=${value.map((v) => encodeURIComponent(v)).join(",")}`)
                  break
                case "indices":
                default:
                  value.forEach((v, i) => parts.push(`${encodeURIComponent(key)}[${i}]=${encodeURIComponent(v)}`))
                  break
              }
            } else if (value !== undefined && value !== null) {
              parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
            }
          }
          return parts.join("&")
        },
        ...config,
      })
      return response.data
    } catch (error: any) {
      throw this.handleError(error)
    }
  }

  // 错误处理
  private handleError(error: any): HttpClientError {
    if (axios.isAxiosError(error)) {
      const message = (error.response?.data as any)?.msg || error.message || "请求失败"
      return new Error(message)
    }
    return error instanceof Error ? error : new Error("未知错误")
  }

  getInstance(): AxiosInstance {
    return this.instance
  }
}

// 创建服务端 HTTP 客户端实例
const serverHttpClient = new ServerHttpClient()

export const serverGet = serverHttpClient.serverGet.bind(serverHttpClient)
export const serverPost = serverHttpClient.serverPost.bind(serverHttpClient)
export const serverPut = serverHttpClient.serverPut.bind(serverHttpClient)
export const serverDelete = serverHttpClient.serverDelete.bind(serverHttpClient)

export type { ApiResponse, RequestConfig, HttpClientError }
export { serverHttpClient }
