const AUTH_KEY = {
	album: 'albumAuthorized',
	camera: 'cameraAuthorized',
	record: 'microphoneAuthorized'
}

const WX_SCOPE = {
	camera: 'scope.camera',
	record: 'scope.record'
}

let modalOpen = false

function t(vm, key, fallback) {
	const fn = vm && vm.$t ? vm.$t.bind(vm) : null
	if (!fn) return fallback
	try {
		const v = fn(key)
		return v && v !== key ? v : fallback
	} catch (_) {
		return fallback
	}
}

function isPermissionErrMsg(msg) {
	const m = String(msg || '').toLowerCase()
	return (
		m.indexOf('auth') !== -1 ||
		m.indexOf('deny') !== -1 ||
		m.indexOf('permission') !== -1 ||
		m.indexOf('authorize') !== -1 ||
		m.indexOf('不允许') !== -1 ||
		m.indexOf('拒绝') !== -1 ||
		m.indexOf('权限') !== -1
	)
}

export function openAppPermissionSettings() {
	if (typeof uni.openAppAuthorizeSetting === 'function') {
		uni.openAppAuthorizeSetting({})
		return
	}
	// #ifdef APP-PLUS
	try {
		const os = String(plus.os.name || '').toLowerCase()
		if (os === 'ios') {
			plus.runtime.openURL('app-settings:')
			return
		}
	} catch (_) {}
	// #endif
	if (typeof uni.openSetting === 'function') {
		uni.openSetting({})
	}
}

function readAppAuthorize(kind) {
	const key = AUTH_KEY[kind]
	if (!key || typeof uni.getAppAuthorizeSetting !== 'function') return 'unknown'
	try {
		const setting = uni.getAppAuthorizeSetting() || {}
		return setting[key] || 'not determined'
	} catch (_) {
		return 'unknown'
	}
}

function contentKeyForKind(kind) {
	if (kind === 'album') return 'dynamics.publishAlbumPermissionContent'
	if (kind === 'record') return 'dynamics.publishRecordPermissionContent'
	return 'dynamics.publishCameraPermissionContent'
}

export function promptMediaPermission(vm, kind) {
	if (modalOpen) return
	modalOpen = true
	uni.showModal({
		title: t(vm, 'dynamics.publishMediaPermissionTitle', '提示'),
		content: t(vm, contentKeyForKind(kind), '请在系统设置中开启相应权限后重试'),
		confirmText: t(vm, 'dynamics.publishMediaPermissionConfirm', '去设置'),
		cancelText: t(vm, 'dynamics.publishMediaPermissionCancel', '取消'),
		success: (res) => {
			modalOpen = false
			if (res.confirm) openAppPermissionSettings()
		},
		fail: () => {
			modalOpen = false
		}
	})
}

function ensureWeixinScope(scope, vm, kind) {
	return new Promise((resolve) => {
		uni.getSetting({
			success: (res) => {
				const auth = (res && res.authSetting) || {}
				if (auth[scope] === false) {
					promptMediaPermission(vm, kind)
					resolve(false)
					return
				}
				if (auth[scope] === true) {
					resolve(true)
					return
				}
				uni.authorize({
					scope,
					success: () => resolve(true),
					fail: () => resolve(false)
				})
			},
			fail: () => resolve(true)
		})
	})
}

export async function ensureMediaPermission(vm, kinds) {
	const list = Array.isArray(kinds) ? kinds : [kinds]
	for (let i = 0; i < list.length; i++) {
		const kind = list[i]
		// #ifdef MP-WEIXIN
		if (kind === 'camera' || kind === 'record') {
			const scope = WX_SCOPE[kind]
			const ok = await ensureWeixinScope(scope, vm, kind)
			if (!ok) return false
			continue
		}
		// 微信小程序读相册由 chooseImage/chooseVideo 触发，fail 回调兜底
		continue
		// #endif

		const status = readAppAuthorize(kind)
		if (status === 'denied') {
			promptMediaPermission(vm, kind)
			return false
		}
	}
	return true
}

function wrapMediaFail(vm, kind, fail) {
	return (err) => {
		if (isPermissionErrMsg(err && err.errMsg)) {
			// 首次拒绝仅静默结束，下次点击时由 ensureMediaPermission 检测 denied 再引导去设置
			return
		}
		if (typeof fail === 'function') fail(err)
	}
}

export function showMediaSourceSheet(vm, options = {}) {
	const { type = 'image', onAlbum, onCamera } = options
	const isVideo = type === 'video'
	uni.showActionSheet({
		itemList: [
			t(vm, 'dynamics.publishPickAlbum', '从相册选择'),
			t(
				vm,
				isVideo ? 'dynamics.publishPickCameraVideo' : 'dynamics.publishPickCamera',
				isVideo ? '拍摄视频' : '拍照'
			)
		],
		success: (res) => {
			if (res.tapIndex === 0 && onAlbum) onAlbum()
			else if (res.tapIndex === 1 && onCamera) onCamera()
		}
	})
}

export async function chooseImageWithPermission(vm, source, options = {}) {
	const kind = source === 'camera' ? 'camera' : 'album'
	const ok = await ensureMediaPermission(vm, kind)
	if (!ok) return
	const { fail, ...rest } = options
	uni.chooseImage({
		...rest,
		sourceType: [source],
		fail: wrapMediaFail(vm, kind, fail)
	})
}

export async function chooseVideoWithPermission(vm, source, options = {}) {
	const kinds = source === 'camera' ? ['camera', 'record'] : ['album']
	const ok = await ensureMediaPermission(vm, kinds)
	if (!ok) return
	const { fail, ...rest } = options
	const failKind = source === 'camera' ? 'camera' : 'album'
	uni.chooseVideo({
		...rest,
		sourceType: [source],
		fail: wrapMediaFail(vm, failKind, fail)
	})
}
