import { getApiBaseUrl, getApiEndpoint, isApiConfigured } from '../config/api.uts'
import { getAccessToken } from './session.uts'
import { request, HttpError } from './http.uts'

export const createIdempotencyKey = (scope: string): string => scope + '-' + Date.now() + '-' + Math.floor(Math.random() * 1000000000)

export const sanitizeRichText = (html: string): string => {
	if (html == null) return ''
	const base = getApiBaseUrl().replace(/\/+$/, '')
	const content = ('' + html)
		.replace(/<script[\s\S]*?<\/script>/gi, '')
		.replace(/<style[\s\S]*?<\/style>/gi, '')
		.replace(/\son[a-z]+\s*=\s*(['"]).*?\1/gi, '')
		// 危险协议（javascript: 等）直接去掉属性。
		.replace(/\s(href|src)\s*=\s*(['"])\s*javascript:[^'"]*\2/gi, '')
	if (base == '') return content
	// 后台富文本里的图片/链接存的是相对路径（/uploads/xxx.png）。小程序加载不了相对路径，
	// 而原来这里会把所有非 https 的 src 整条删掉，图片就变成破图（只显示 alt 文字）。
	// 这里统一补成接口域名下的绝对地址，http(s) 绝对地址原样保留。
	return content
		// 小程序 rich-text 不认 <s>/<strike>/<u>，换成它支持的 <del>/<ins>，
		// 否则后台设的删除线/下划线在人才端看不见（看着像"样式没生效"）。
		.replace(/<\s*(\/?)\s*s(?=[\s>/])([^>]*)>/gi, '<$1del$2>')
		.replace(/<\s*(\/?)\s*strike(?=[\s>/])([^>]*)>/gi, '<$1del$2>')
		.replace(/<\s*(\/?)\s*u(?=[\s>/])([^>]*)>/gi, '<$1ins$2>')
		.replace(/(src|href)=(["'])\/\//gi, '$1=$2https://')
		.replace(/(\s(?:src|href)\s*=\s*(['"]))\/+/gi, '$1' + base + '/')
		.replace(/(\s(?:src|href)\s*=\s*(['"]))(?!https?:|\/\/|\/|data:|javascript:)/gi, '$1' + base + '/')
		// 小程序 rich-text 不继承页面样式：后台图片带的是原图尺寸，会撑出卡片。
		// 在图片标签上补内联样式，按容器宽度等比缩放并居中。
		.replace(/(<img\b[^>]*?\sstyle=(["']))([^"']*)(\2)/gi, '$1$3max-width:100%;height:auto;display:block;margin:10px auto;$4')
		.replace(/<img\b(?![^>]*\sstyle=)/gi, '<img style="max-width:100%;height:auto;display:block;margin:10px auto;"')
}

export const requestDynamicCode = (codeType: string, businessId: string, onSuccess: (data: any) => void, onError: (error: HttpError) => void) => {
	request<any>({ path: getApiEndpoint('dynamicCode'), method: 'POST', data: { codeType: codeType, businessId: businessId } }, onSuccess, onError)
}

export const claimCoupon = (couponId: string, onSuccess: (data: any) => void, onError: (error: HttpError) => void) => {
	request<any>({ path: getApiEndpoint('couponClaim'), method: 'POST', data: { couponId: couponId }, idempotencyKey: createIdempotencyKey('coupon') }, onSuccess, onError)
}

export const getCouponDetail = (userCouponId: string, onSuccess: (data: any) => void, onError: (error: HttpError) => void) => {
	request<any>({ path: getApiEndpoint('couponDetail'), method: 'GET', data: { userCouponId: userCouponId } }, onSuccess, onError)
}

export const getRecordDetail = (recordId: string, onSuccess: (data: any) => void, onError: (error: HttpError) => void) => {
	request<any>({ path: getApiEndpoint('recordDetail'), method: 'GET', data: { recordId: recordId } }, onSuccess, onError)
}

export const submitBusiness = (businessType: string, payload: any, onSuccess: (data: any) => void, onError: (error: HttpError) => void) => {
	request<any>({ path: getApiEndpoint('businessSubmit'), method: 'POST', data: { businessType: businessType, payload: payload }, idempotencyKey: createIdempotencyKey(businessType) }, onSuccess, onError)
}

export const payOrder = (orderId: string, onSuccess: (data: any) => void, onError: (error: HttpError) => void) => {
	request<any>({ path: getApiEndpoint('orderPayment'), method: 'POST', data: { orderId: orderId }, idempotencyKey: createIdempotencyKey('payment') }, (payment: any) => {
		if (payment == null || payment.timeStamp == null || payment.nonceStr == null || payment.package == null || payment.paySign == null) {
			onError({ code: 'INVALID_PAYMENT_RESPONSE', message: '支付参数不完整', statusCode: 200, traceId: '' })
			return
		}
		uni.requestPayment({
			provider: 'wxpay',
			timeStamp: payment.timeStamp,
			nonceStr: payment.nonceStr,
			package: payment.package,
			signType: payment.signType != null ? payment.signType : 'RSA',
			paySign: payment.paySign,
			success: () => request<any>({ path: getApiEndpoint('orderPaymentResult'), method: 'GET', data: { orderId: orderId } }, onSuccess, onError),
			fail: () => onError({ code: 'PAYMENT_CANCELLED', message: '支付未完成', statusCode: 0, traceId: '' })
		})
	}, onError)
}

export const uploadProofFile = (filePath: string, businessType: string, onSuccess: (data: any) => void, onError: (error: HttpError) => void, onProgress?: (progress: number) => void): (() => void) => {
	const endpoint = getApiEndpoint('fileUpload')
	if (!isApiConfigured() || endpoint.length == 0) {
		onError({ code: 'API_NOT_CONFIGURED', message: '上传服务尚未配置', statusCode: 0, traceId: '' })
		return () => {}
	}
	const lowerPath = filePath.toLowerCase()
	if (!(/\.(jpg|jpeg|png|webp|pdf)$/).test(lowerPath)) {
		onError({ code: 'UNSUPPORTED_FILE', message: '仅支持 JPG、PNG、WEBP 或 PDF 文件', statusCode: 0, traceId: '' })
		return () => {}
	}
	let task: any = null
	let cancelled = false
	uni.getFileInfo({
		filePath: filePath,
		success: (file: any) => {
			if (cancelled) return
			if (file.size != null && file.size > 10 * 1024 * 1024) {
				onError({ code: 'FILE_TOO_LARGE', message: '文件不能超过 10MB', statusCode: 0, traceId: '' })
				return
			}
			task = uni.uploadFile({
				url: getApiBaseUrl().replace(/\/$/, '') + '/' + endpoint.replace(/^\//, ''),
				filePath: filePath,
				name: 'file',
				formData: { businessType: businessType },
				header: { Authorization: 'Bearer ' + getAccessToken(), 'X-Idempotency-Key': createIdempotencyKey('upload') },
				success: (response: any) => {
					try {
						const payload: any = JSON.parse(response.data as string)
						if (response.statusCode >= 200 && response.statusCode < 300 && (payload.code == null || payload.code == 0 || payload.code == 200)) onSuccess(payload.data != null ? payload.data : payload)
						else onError({ code: payload.code != null ? '' + payload.code : 'UPLOAD_FAILED', message: payload.message != null ? payload.message as string : '上传失败', statusCode: response.statusCode, traceId: payload.traceId != null ? payload.traceId as string : '' })
					} catch (_) {
						onError({ code: 'INVALID_UPLOAD_RESPONSE', message: '上传响应格式错误', statusCode: response.statusCode, traceId: '' })
					}
				},
				fail: () => onError({ code: cancelled ? 'UPLOAD_CANCELLED' : 'UPLOAD_NETWORK_ERROR', message: cancelled ? '已取消上传' : '上传失败，请检查网络后重试', statusCode: 0, traceId: '' })
			})
			if (onProgress != null) task.onProgressUpdate((progress: any) => onProgress(progress.progress as number))
		},
		fail: () => onError({ code: 'FILE_READ_FAILED', message: '无法读取待上传文件', statusCode: 0, traceId: '' })
	})
	return () => { cancelled = true; if (task != null) task.abort() }
}
