/**
 * API 服务基类
 * 提供统一的 HTTP 请求方法
 */

import request from '@/utils/http'
import type { BaseResponse, PaginationResponse, ListResponse } from '@/types/api'

export class BaseService {
  /**
   * GET 请求
   * @param url 请求URL
   * @param params 请求参数
   * @param config 额外配置
   */
  protected static get<T = any>(
    url: string,
    params?: Record<string, any>,
    config?: Record<string, any>
  ): Promise<T> {
    return request.get<T>({
      url,
      params,
      ...config
    })
  }

  /**
   * POST 请求
   * @param url 请求URL
   * @param data 请求数据
   * @param config 额外配置
   */
  protected static post<T = any>(
    url: string,
    data?: Record<string, any>,
    config?: Record<string, any>
  ): Promise<T> {
    return request.post<T>({
      url,
      data,
      ...config
    })
  }

  /**
   * PUT 请求
   * @param url 请求URL
   * @param data 请求数据
   * @param config 额外配置
   */
  protected static put<T = any>(
    url: string,
    data?: Record<string, any>,
    config?: Record<string, any>
  ): Promise<T> {
    return request.put<T>({
      url,
      data,
      ...config
    })
  }

  /**
   * PATCH 请求
   * @param url 请求URL
   * @param data 请求数据
   * @param config 额外配置
   */
  protected static patch<T = any>(
    url: string,
    data?: Record<string, any>,
    config?: Record<string, any>
  ): Promise<T> {
    return request.patch<T>({
      url,
      data,
      ...config
    })
  }

  /**
   * DELETE 请求
   * @param url 请求URL
   * @param params 请求参数
   * @param config 额外配置
   */
  protected static delete<T = any>(
    url: string,
    params?: Record<string, any>,
    config?: Record<string, any>
  ): Promise<T> {
    return request.del<T>({
      url,
      params,
      ...config
    })
  }

  /**
   * 获取单个资源
   * @param url 请求URL
   * @param params 请求参数
   * @param config 额外配置
   */
  protected static getOne<T>(
    url: string,
    params?: Record<string, any>,
    config?: Record<string, any>
  ): Promise<BaseResponse<T>> {
    return this.get<BaseResponse<T>>(url, params, config)
  }

  /**
   * 获取列表（不分页）
   * @param url 请求URL
   * @param params 请求参数
   */
  protected static getList<T>(url: string, params?: Record<string, any>): Promise<ListResponse<T>> {
    return this.get<ListResponse<T>>(url, params)
  }

  /**
   * 获取分页列表
   * @param url 请求URL
   * @param params 请求参数
   */
  protected static getPage<T>(
    url: string,
    params?: Record<string, any>
  ): Promise<PaginationResponse<T>> {
    return this.get<PaginationResponse<T>>(url, params)
  }

  /**
   * 创建资源
   * @param url 请求URL
   * @param data 请求数据
   */
  protected static create<T = any>(
    url: string,
    data: Record<string, any>
  ): Promise<BaseResponse<T>> {
    return this.post<BaseResponse<T>>(url, data)
  }

  /**
   * 更新资源
   * @param url 请求URL
   * @param data 请求数据
   */
  protected static update<T = any>(
    url: string,
    data: Record<string, any>
  ): Promise<BaseResponse<T>> {
    return this.put<BaseResponse<T>>(url, data)
  }

  /**
   * 删除资源
   * @param url 请求URL
   * @param params 请求参数
   */
  protected static remove<T = any>(
    url: string,
    params?: Record<string, any>
  ): Promise<BaseResponse<T>> {
    return this.delete<BaseResponse<T>>(url, params)
  }

  /**
   * 批量删除
   * @param url 请求URL
   * @param ids ID列表
   */
  protected static batchDelete(url: string, ids: (string | number)[]): Promise<BaseResponse> {
    return this.delete<BaseResponse>(url, { ids })
  }

  /**
   * 上传文件
   * @param url 请求URL
   * @param file 文件
   * @param params 额外参数
   */
  protected static upload<T = any>(
    url: string,
    file: File,
    params?: Record<string, any>
  ): Promise<BaseResponse<T>> {
    const formData = new FormData()
    formData.append('file', file)

    if (params) {
      Object.keys(params).forEach((key) => {
        if (params[key] !== undefined && params[key] !== null && params[key] !== '') {
          formData.append(key, String(params[key]))
        }
      })
    }

    // 不要手动设置 Content-Type,让浏览器自动设置(包含正确的 boundary)
    return request.post<BaseResponse<T>>({
      url,
      data: formData
    })
  }

  /**
   * 下载文件
   * @param url 请求URL
   * @param params 请求参数
   * @param fileName 文件名
   */
  protected static download(
    url: string,
    params?: Record<string, any>,
    fileName?: string
  ): Promise<void> {
    return request
      .get({
        url,
        params,
        responseType: 'blob'
      })
      .then((blob: any) => {
        const downloadUrl = window.URL.createObjectURL(blob)
        const link = document.createElement('a')
        link.href = downloadUrl
        link.download = fileName || 'download'
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        window.URL.revokeObjectURL(downloadUrl)
      })
  }
}
