import { getAccessToken, clearSession } from './session.uts'
import { getApiBaseUrl, isApiConfigured } from '../config/api.uts'

export type HttpError = {
	code: string
	message: string
	statusCode: number
	traceId: string
}

export type HttpRequestOptions = {
	path: string
	method?: string
	data?: any
	idempotencyKey?: string
	skipAuth?: boolean
}

const requestTimeout = 15000

const createRequestId = (): string => 'tc-' + Date.now() + '-' + Math.floor(Math.random() * 1000000)
const buildUrl = (path: string): string => {
	const baseUrl = getApiBaseUrl()
	if (path.indexOf('http://') == 0 || path.indexOf('https://') == 0) return path
	return baseUrl.replace(/\/$/, '') + '/' + path.replace(/^\//, '')
}

export const resolveApiUrl = (path: string): string => {
	if (path.indexOf('/uploads/') == 0 || path.indexOf('/api/') == 0) return buildUrl(path)
	return path
}
const unavailable = (): HttpError => ({ code: 'API_NOT_CONFIGURED', message: '后台服务尚未配置', statusCode: 0, traceId: '' })

export const request = <T>(options: HttpRequestOptions, onSuccess: (data: T, traceId: string) => void, onError: (error: HttpError) => void): (() => void) => {
	if (!isApiConfigured() || options.path.length == 0) {
		onError(unavailable())
		return () => {}
	}
	const headers: any = {
		'Content-Type': 'application/json',
		'X-Request-Id': createRequestId()
	}
	if (!options.skipAuth) {
		const token = getAccessToken()
		if (token.length > 0) headers['Authorization'] = 'Bearer ' + token
	}
	if (options.idempotencyKey != null && options.idempotencyKey.length > 0) headers['X-Idempotency-Key'] = options.idempotencyKey
	const task: any = uni.request({
		url: buildUrl(options.path),
		method: options.method != null ? options.method : 'GET',
		data: options.data,
		header: headers,
		timeout: requestTimeout,
		success: (response: any) => {
			const payload: any = response.data
			const traceId = payload != null && payload.traceId != null ? payload.traceId as string : ''
			const businessCode = payload != null && payload.code != null ? payload.code : 0
			if (response.statusCode == 401) {
				clearSession()
				onError({ code: 'UNAUTHORIZED', message: '登录已失效，请重新登录', statusCode: 401, traceId: traceId })
				return
			}
			if (response.statusCode < 200 || response.statusCode >= 300) {
				onError({ code: 'HTTP_' + response.statusCode, message: payload != null && payload.message != null ? payload.message as string : '服务暂不可用', statusCode: response.statusCode, traceId: traceId })
				return
			}
			if (businessCode != 0 && businessCode != 200) {
				onError({ code: '' + businessCode, message: payload != null && payload.message != null ? payload.message as string : '业务处理失败', statusCode: response.statusCode, traceId: traceId })
				return
			}
			onSuccess((payload != null && payload.data != null ? payload.data : payload) as T, traceId)
		},
		fail: (error: any) => onError({ code: 'NETWORK_ERROR', message: error != null && error.errMsg != null ? error.errMsg as string : '网络连接失败，请稍后重试', statusCode: 0, traceId: '' })
	})
	return () => task.abort()
}
