import type { ApiResult } from '@/types/api'
import { alovaInstance } from './instance'
import { ApiError } from './handlers'

function unwrapApiResult<T>(response: ApiResult<T>, fallbackMessage: string): T {
  if (response.code === 401 || response.code === 403) {
    throw new ApiError(response.message || '登录已过期，请重新登录！', response.code, response)
  }
  if (!response.success) {
    throw new ApiError(response.message || fallbackMessage, response.code || 500, response)
  }
  return response.result
}

export function withMiniTokenHeader(token?: string | null) {
  if (!token) {
    return undefined
  }
  return {
    headers: {
      'Mini-Authorization': token,
    },
    // Some uni request chains still read singular `header`, keep both in sync.
    header: {
      'Mini-Authorization': token,
    },
  }
}

export async function getResult<T>(url: string, config?: Parameters<typeof alovaInstance.Get>[1]): Promise<T> {
  const response = await alovaInstance.Get<ApiResult<T>>(url, config).send()
  return unwrapApiResult(response, '请求失败')
}

export async function getPageResult<T>(
  url: string,
  config?: Parameters<typeof alovaInstance.Get>[1],
): Promise<ApiResult<T>> {
  const response = await alovaInstance.Get<ApiResult<T>>(url, config).send()
  unwrapApiResult(response, '请求失败')
  return response
}

export async function postResult<T>(
  url: string,
  data?: unknown,
  config?: Parameters<typeof alovaInstance.Post>[2],
): Promise<T> {
  const response = await alovaInstance.Post<ApiResult<T>>(url, data, config).send()
  return unwrapApiResult(response, '请求失败')
}

export async function putResult<T>(
  url: string,
  data?: unknown,
  config?: Parameters<typeof alovaInstance.Put>[2],
): Promise<T> {
  const response = await alovaInstance.Put<ApiResult<T>>(url, data, config).send()
  return unwrapApiResult(response, '请求失败')
}

export async function patchResult<T>(
  url: string,
  data?: unknown,
  config?: Parameters<typeof alovaInstance.Patch>[2],
): Promise<T> {
  const response = await alovaInstance.Patch<ApiResult<T>>(url, data, config).send()
  return unwrapApiResult(response, '请求失败')
}

export async function deleteResult<T>(
  url: string,
  config?: Parameters<typeof alovaInstance.Delete>[2],
): Promise<T> {
  const response = await alovaInstance.Delete<ApiResult<T>>(url, undefined, config).send()
  return unwrapApiResult(response, '请求失败')
}
