import { BaseApi } from './baseApi.js'
import api from './index.js'

const OPEN_DOCUMENT_EXTENSIONS = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx']
const TEXT_PREVIEW_EXTENSIONS = ['txt', 'md', 'csv']
const MAX_TEXT_PREVIEW_SIZE = 256 * 1024

function parseResult(response) {
	let result = response && response.data
	if (typeof result === 'string') {
		try {
			result = JSON.parse(result)
		} catch (error) {
			throw new Error('上传失败，请重试')
		}
	}
	if (!response || response.statusCode !== 200 || !result || result.code !== 0) {
		throw new Error(result && result.msg ? result.msg : '上传失败，请重试')
	}
	return result.data
}

function unwrap(response) {
	const result = response && response.data
	if (!result || result.code !== 0) {
		throw new Error(result && result.msg ? result.msg : '请求失败，请重试')
	}
	return result.data
}

function getHeader(headers, name) {
	if (!headers || typeof headers !== 'object') return ''
	const expectedName = name.toLowerCase()
	for (const key of Object.keys(headers)) {
		if (key.toLowerCase() === expectedName) return String(headers[key] || '')
	}
	return ''
}

function isSafeAttachment(headers) {
	const contentType = getHeader(headers, 'content-type').split(';')[0].trim().toLowerCase()
	const disposition = getHeader(headers, 'content-disposition').trim()
	if (!contentType || !/^attachment(?:\s*;|$)/i.test(disposition)) return false
	if (contentType === 'application/json' || contentType === 'text/json'
		|| contentType.endsWith('+json') || contentType === 'text/html'
		|| contentType === 'application/xhtml+xml') return false
	return true
}

function getDownloadFileName(headers) {
	const disposition = getHeader(headers, 'content-disposition')
	const encodedMatch = disposition.match(/(?:^|;)\s*filename\*\s*=\s*UTF-8''([^;]*)/i)
	if (encodedMatch) {
		try {
			const decoded = decodeURIComponent(encodedMatch[1].trim())
			if (decoded) return decoded
		} catch (error) {
			// Fall back to the compatible ASCII filename below.
		}
	}
	const fallbackMatch = disposition.match(/(?:^|;)\s*filename\s*=\s*(?:"([^"]*)"|([^;]*))/i)
	return fallbackMatch ? String(fallbackMatch[1] || fallbackMatch[2] || '').trim() : ''
}

function getFileExtension(fileName) {
	const extensionIndex = fileName.lastIndexOf('.')
	if (extensionIndex < 0 || extensionIndex === fileName.length - 1) return ''
	return fileName.slice(extensionIndex + 1).toLowerCase()
}

function readTextPreview(filePath, fileName) {
	return new Promise((resolve, reject) => {
		const fail = () => reject(new Error('文件读取失败，请重试'))
		let fileSystem
		try {
			fileSystem = typeof wx !== 'undefined' && typeof wx.getFileSystemManager === 'function'
				? wx.getFileSystemManager()
				: null
		} catch (error) {
			fail()
			return
		}
		if (!fileSystem || typeof fileSystem.getFileInfo !== 'function'
			|| typeof fileSystem.readFile !== 'function') {
			fail()
			return
		}
		try {
			fileSystem.getFileInfo({
				filePath,
				success: info => {
					const size = Number(info && info.size)
					if (!Number.isFinite(size) || size < 0) {
						fail()
						return
					}
					if (size === 0) {
						resolve({ mode: 'text', fileName, content: '', truncated: false })
						return
					}
					try {
						fileSystem.readFile({
							filePath,
							encoding: 'utf8',
							position: 0,
							length: Math.min(size, MAX_TEXT_PREVIEW_SIZE),
							success: result => {
								if (!result || typeof result.data !== 'string') {
									fail()
									return
								}
								resolve({
									mode: 'text',
									fileName,
									content: result.data,
									truncated: size > MAX_TEXT_PREVIEW_SIZE
								})
							},
							fail
						})
					} catch (error) {
						fail()
					}
				},
				fail
			})
		} catch (error) {
			fail()
		}
	})
}

export function uploadTeamBackgroundFile(teamId, filePath, onProgress = () => {}) {
	return new Promise((resolve, reject) => {
		const task = uni.uploadFile({
			url: `${BaseApi}/core/user/team/${teamId}/background-files`,
			filePath,
			name: 'file',
			header: { token: uni.getStorageSync('token') },
			success: response => {
				try {
					resolve(parseResult(response))
				} catch (error) {
					reject(error)
				}
			},
			fail: reject
		})
		task.onProgressUpdate(progress => onProgress(progress.progress))
	})
}

export const listTeamBackgroundFiles = teamId => api
	.get(`/core/user/team/${teamId}/background-files`, {}, false)
	.then(unwrap)

export const disableTeamBackgroundFile = (teamId, fileId) => api
	.del(`/core/user/team/${teamId}/background-files/${fileId}`, {}, false)
	.then(unwrap)

export const createTeamBackgroundSession = teamId => api
	.post(`/core/user/team/${teamId}/background-upload-session`, {}, false)
	.then(unwrap)

export function downloadTeamBackgroundFile(teamId, fileId) {
	return new Promise((resolve, reject) => {
		let responseHeaders
		const task = uni.downloadFile({
			url: `${BaseApi}/core/user/team/${teamId}/background-files/${fileId}/download`,
			header: { token: uni.getStorageSync('token') },
			success: result => {
				const resultHeaders = result && (result.header || result.headers)
				const headers = responseHeaders || resultHeaders
				if (!result || result.statusCode !== 200
					|| !isSafeAttachment(headers)) {
					reject(new Error('下载失败，请重试'))
					return
				}
				const fileName = getDownloadFileName(headers)
				const extension = getFileExtension(fileName)
				if (OPEN_DOCUMENT_EXTENSIONS.includes(extension)) {
					resolve({ mode: 'document', fileName, filePath: result.tempFilePath })
					return
				}
				if (TEXT_PREVIEW_EXTENSIONS.includes(extension)) {
					readTextPreview(result.tempFilePath, fileName).then(resolve, reject)
					return
				}
				reject(new Error('文件类型不支持预览'))
			},
			fail: reject
		})
		if (task && typeof task.onHeadersReceived === 'function') {
			task.onHeadersReceived(result => {
				responseHeaders = result && (result.header || result.headers)
			})
		}
	})
}
