'use strict';
let uniID = require('uni-id')
const uniCaptcha = require('uni-captcha')
const createConfig = require('uni-config-center')
const uniIdConfig = createConfig({
	pluginId: 'uni-id'
}).config()
const db = uniCloud.database()
const dbCmd = db.command
const usersDB = db.collection('uni-id-users')
exports.main = async (event, context) => {
	//UNI_WYQ:这里的uniID换成新的，保证多人访问不会冲突
	uniID = uniID.createInstance({
		context
	})
	console.log('event : ' + JSON.stringify(event))
	/*
	1.event为客户端 uniCloud.callFunction填写的data的值，这里介绍一下其中的属性
	  action：表示要执行的任务名称、比如：登陆login、退出登陆 logout等
	  params：业务数据内容
	  uniIdToken：系统自动传递的token，数据来源客户端的 uni.getStorageSync('uni_id_token')
	*/
	const {
		action,
		uniIdToken,
		inviteCode
	} = event;
	const deviceInfo = event.deviceInfo || {};
	let params = event.params || {};
	/*
	2.在某些操作之前我们要对用户对身份进行校验（也就是要检查用户的token）再将得到的uid写入params.uid
	  校验用到的方法是uniID.checkToken 详情：https://uniapp.dcloud.io/uniCloud/uni-id?id=checktoken

	  讨论，我们假设一个这样的场景，代码如下。
	  如：
		uniCloud.callFunction({
			name:"xxx",
			data:{
				"params":{
					uid:"通过某种方式获取来的别人的uid"
				}
			}
		})
	  用户就这样轻易地伪造了他人的uid传递给服务端，有一句话叫：前端从来的数据是不可信任的
	  所以这里我们需要将uniID.checkToken返回的uid写入到params.uid
	*/
	let noCheckAction = ['register', 'checkToken', 'login', 'logout', 'sendSmsCode', 'createCaptcha',
		'verifyCaptcha', 'refreshCaptcha', 'inviteLogin', 'loginByWeixin', 'loginByUniverify',
		'loginByApple', 'loginBySms', 'resetPwdBySmsCode', 'registerAdmin'
	]
	if (!noCheckAction.includes(action)) {
		if (!uniIdToken) {
			return {
				code: 403,
				msg: '缺少token'
			}
		}
		let payload = await uniID.checkToken(uniIdToken)
		if (payload.code && payload.code > 0) {
			return payload
		}
		params.uid = payload.uid
	}

	//禁止前台用户传递角色
	if (action.slice(0, 7) == "loginBy") {
		if (params.role) {
			return {
				code: 403,
				msg: '禁止前台用户传递角色'
			}
		}
	}

	//3.注册成功后创建新用户的积分表方法
	async function registerSuccess(uid) {
		//用户接受邀请
		if (inviteCode) {
			await uniID.acceptInvite({
				inviteCode,
				uid
			});
		}
		//添加当前用户设备信息
		await db.collection('uni-id-device').add({
			...deviceInfo,
			user_id: uid
		})
		await db.collection('uni-id-scores').add({
			user_id: uid,
			score: 1,
			type: 1,
			balance: 1,
			comment: "",
			create_date: Date.now()
		})
	}
	//4.记录成功登录的日志方法
	const loginLog = async (res = {}) => {
		const now = Date.now()
		const uniIdLogCollection = db.collection('uni-id-log')
		let logData = {
			deviceId: params.deviceId || context.DEVICEID,
			ip: params.ip || context.CLIENTIP,
			type: res.type,
			ua: context.CLIENTUA,
			create_date: now
		};

		Object.assign(logData,
			res.code === 0 ? {
				user_id: res.uid,
				state: 1
			} : {
				state: 0
			})
		if (res.type == 'register') {
			await registerSuccess(res.uid)
		} else {
			if (Object.keys(deviceInfo).length) {
				console.log(979797, {
					deviceInfo,
					user_id: res
				});
				//更新当前用户设备信息
				await db.collection('uni-id-device').where({
					user_id: res.uid
				}).update(deviceInfo)
			}
		}
		return await uniIdLogCollection.add(logData)
	}

	let res = {}
	switch (action) { //根据action的值执行对应的操作
		case 'bindMobileByUniverify':
			let {
				appid, apiKey, apiSecret
			} = uniIdConfig.service.univerify
			let univerifyRes = await uniCloud.getPhoneNumber({
				provider: 'univerify',
				appid,
				apiKey,
				apiSecret,
				access_token: params.access_token,
				openid: params.openid
			})
			if (univerifyRes.code === 0) {
				res = await uniID.bindMobile({
					uid: params.uid,
					mobile: univerifyRes.phoneNumber
				})
				res.mobile = univerifyRes.phoneNumber
			}
			break;
		case 'bindMobileBySms':
			// console.log({
			// 	uid: params.uid,
			// 	mobile: params.mobile,
			// 	code: params.code
			// });
			res = await uniID.bindMobile({
				uid: params.uid,
				mobile: params.mobile,
				code: params.code
			})
			// console.log(res);
			break;
		case 'register':
			var {
				username, password, nickname
			} = params
			if (/^1\d{10}$/.test(username)) {
				return {
					code: 401,
					msg: '用户名不能是手机号'
				}
			};
			if (/^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/.test(username)) {
				return {
					code: 401,
					msg: '用户名不能是邮箱'
				}
			}
			res = await uniID.register({
				username,
				password,
				nickname,
				inviteCode
			});
			if (res.code === 0) {
				await registerSuccess(res.uid)
			}
			break;
		case 'login':
			//防止黑客恶意破解登录，连续登录失败一定次数后，需要用户提供验证码
			const getNeedCaptcha = async () => {
				//当用户最近“2小时内(recordDate)”登录失败达到2次(recordSize)时。要求用户提交验证码
				const now = Date.now(),
					recordDate = 120 * 60 * 1000,
					recordSize = 2;
				const uniIdLogCollection = db.collection('uni-id-log')
				let recentRecord = await uniIdLogCollection.where({
						deviceId: params.deviceId || context.DEVICEID,
						create_date: dbCmd.gt(now - recordDate),
						type: 'login'
					})
					.orderBy('create_date', 'desc')
					.limit(recordSize)
					.get();
				return recentRecord.data.filter(item => item.state === 0).length === recordSize;
			}

			let passed = false;
			let needCaptcha = await getNeedCaptcha();
			console.log('needCaptcha', needCaptcha);
			if (needCaptcha) {
				res = await uniCaptcha.verify({
					...params,
					scene: 'login'
				})
				if (res.code === 0) passed = true;
			}

			if (!needCaptcha || passed) {
				res = await uniID.login({
					...params,
					queryField: ['username', 'email', 'mobile']
				});
				res.type = 'login'
				await loginLog(res);
				needCaptcha = await getNeedCaptcha();
			}

			res.needCaptcha = needCaptcha;
			break;
		case 'loginByWeixin':
			res = await uniID.loginByWeixin(params);
			await uniID.updateUser({
				uid: res.uid,
				username: "微信用户"
			});
			res.userInfo.username = "微信用户"
			await loginLog(res)
			break;
		case 'loginByUniverify':
			res = await uniID.loginByUniverify(params)
			await loginLog(res)
			break;
		case 'loginByApple':
			res = await uniID.loginByApple(params)
			await loginLog(res)
			break;
		case 'checkToken':
			res = await uniID.checkToken(uniIdToken);
			break;
		case 'logout':
			res = await uniID.logout(uniIdToken)
			break;
		case 'sendSmsCode':
			/* -开始- 测试期间，为节约资源。统一虚拟短信验证码为： 123456；开启以下代码块即可  */
			// return uniID.setVerifyCode({
			// 	mobile: params.mobile,
			// 	code: '123456',
			// 	type: params.type
			// })
			/* -结束- */

			// 简单限制一下客户端调用频率
			const ipLimit = await db.collection('opendb-verify-codes').where({
				ip: context.CLIENTIP,
				created_at: dbCmd.gt(Date.now() - 60000)
			}).get()
			if (ipLimit.data.length > 0) {
				return {
					code: 429,
					msg: '请求过于频繁'
				}
			}
			const templateId = '11753' // 替换为自己申请的模板id
			if (!templateId) {
				return {
					code: 500,
					msg: 'sendSmsCode需要传入自己的templateId，参考https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=sendsmscode'
				}
			}
			const randomStr = '00000' + Math.floor(Math.random() * 1000000)
			const code = randomStr.substring(randomStr.length - 6)
			res = await uniID.sendSmsCode({
				mobile: params.mobile,
				code,
				type: params.type,
				templateId
			})
			break;
		case 'loginBySms':
			if (!params.code) {
				return {
					code: 500,
					msg: '请填写验证码'
				}
			}
			if (!/^1\d{10}$/.test(params.mobile)) {
				return {
					code: 500,
					msg: '手机号码填写错误'
				}
			}
			res = await uniID.loginBySms(params)
			await loginLog(res)
			break;
		case 'resetPwdBySmsCode':
			if (!params.code) {
				return {
					code: 500,
					msg: '请填写验证码'
				}
			}
			if (!/^1\d{10}$/.test(params.mobile)) {
				return {
					code: 500,
					msg: '手机号码填写错误'
				}
			}
			params.type = 'login'
			let loginBySmsRes = await uniID.loginBySms(params)
			// console.log(loginBySmsRes);
			if (loginBySmsRes.code === 0) {
				res = await uniID.resetPwd({
					password: params.password,
					"uid": loginBySmsRes.uid
				})
			} else {
				return loginBySmsRes
			}
			break;
		case 'getInviteCode':
			res = await uniID.getUserInfo({
				uid: params.uid,
				field: ['my_invite_code']
			})
			if (res.code === 0) {
				res.myInviteCode = res.userInfo.my_invite_code
				delete res.userInfo
			}
			break;
		case 'getInvitedUser':
			res = await uniID.getInvitedUser(params)
			break;
		case 'updatePwd':
			res = await uniID.updatePwd(params)
			break;
		case 'createCaptcha':
			res = await uniCaptcha.create(params)
			break;
		case 'refreshCaptcha':
			res = await uniCaptcha.refresh(params)
			break;
		case 'getUserInviteCode':
			res = await uniID.getUserInfo({
				uid: params.uid,
				field: ['my_invite_code']
			})
			if (!res.userInfo.my_invite_code) {
				res = await uniID.setUserInviteCode({
					uid: params.uid
				})
			}
			break;

			// =========================== admin api start =========================
		case 'registerAdmin': {
			var {
				username,
				password
			} = params
			let {
				total
			} = await db.collection('uni-id-users').where({
				role: 'admin'
			}).count()
			if (total) {
				return {
					code: 10001,
					message: '超级管理员已存在，请登录...'
				}
			}
			const appid = params.appid
			const appName = params.appName
			delete params.appid
			delete params.appName
			res = await uniID.register({
				username,
				password,
				role: ["admin"]
			})
			if (res.code === 0) {
				const app = await db.collection('opendb-app-list').where({
					appid
				}).count()
				if (!app.total) {
					await db.collection('opendb-app-list').add({
						appid,
						name: appName,
						description: "admin 管理后台",
						create_date: Date.now()
					})
				}

			}
		}
		break;
	case 'registerUser':
		const {
			userInfo
		} = await uniID.getUserInfo({
			uid: params.uid
		})
		if (userInfo.role.indexOf('admin') === -1) {
			res = {
				code: 403,
				message: '非法访问, 无权限注册超级管理员',
			}
		} else {
			// 过滤 dcloud_appid，注册用户成功后再提交
			const dcloudAppidList = params.dcloud_appid
			delete params.dcloud_appid
			res = await uniID.register({
				autoSetDcloudAppid: false,
				...params
			})
			if (res.code === 0) {
				delete res.token
				delete res.tokenExpired
				await uniID.setAuthorizedAppLogin({
					uid: res.uid,
					dcloudAppidList
				})
			}
		}
		break;
	case 'updateUser': {
		const {
			userInfo
		} = await uniID.getUserInfo({
			uid: params.uid
		})
		if (userInfo.role.indexOf('admin') === -1) {
			res = {
				code: 403,
				message: '非法访问, 无权限注册超级管理员',
			}
		} else {
			// 过滤 dcloud_appid，注册用户成功后再提交
			const dcloudAppidList = params.dcloud_appid
			delete params.dcloud_appid

			// 过滤 password，注册用户成功后再提交
			const password = params.password
			delete params.password

			// 过滤 uid、id
			const id = params.id
			delete params.id
			delete params.uid


			res = await uniID.updateUser({
				uid: id,
				...params
			})
			if (res.code === 0) {
				if (password) {
					await uniID.resetPwd({
						uid: id,
						password
					})
				}
				await uniID.setAuthorizedAppLogin({
					uid: id,
					dcloudAppidList
				})
			}
		}
		break;
	}
	case 'getCurrentUserInfo':
		res = await uniID.getUserInfo({
			uid: params.uid,
			...params
		})
		break;
		// =========================== admin api end =========================
	default:
		res = {
			code: 403,
			msg: '非法访问'
		}
		break;
	}
	//返回数据给客户端
	return res
}
