/**
 * @class ActiveUsers 活跃用户模型 - 每日跑批合并，仅添加本周/本月首次访问的用户。
 */
const BaseMod = require('./base')
const Platform = require('./platform')
const Channel = require('./channel')
const Version = require('./version')
const UserSessionLog = require('./userSessionLog')
const {
	DateTime,
	UniCrypto
} = require('../lib')
module.exports = class ActiveUsers extends BaseMod {
	constructor() {
		super()
		this.tableName = 'active-users'
		this.platforms = []
		this.channels = []
		this.versions = []
	}

	async stat(date, reset) {
		const dateTime = new DateTime()
		const dateDimension = dateTime.getTimeDimensionByType('day', -1, date)
		this.startTime = dateDimension.startTime
		// 查看当前时间段数据是否已存在,防止重复生成
		if (!reset) {
			const checkRes = await this.getCollection(this.tableName).where({
				create_time: {
					$gte: dateDimension.startTime,
					$lte: dateDimension.endTime
				}
			}).get()
			if (checkRes.data.length > 0) {
				console.log('data have exists')
				return {
					code: 1003,
					msg: 'Users data in this time have already existed'
				}
			}
		} else {
			const delRes = await this.delete(this.tableName, {
				create_time: {
					$gte: dateDimension.startTime,
					$lte: dateDimension.endTime
				}
			})
			console.log('Delete old data result:', JSON.stringify(delRes))
		}

		const userSessionLog = new UserSessionLog()
		const statRes = await this.aggregate(userSessionLog.tableName, {
			project: {
				appid: 1,
				version: 1,
				platform: 1,
				channel: 1,
				create_time: 1,
				uid: 1
			},
			match: {
				create_time: {
					$gte: dateDimension.startTime,
					$lte: dateDimension.endTime
				}
			},
			group: {
				_id: {
					appid: '$appid',
					version: '$version',
					platform: '$platform',
					channel: '$channel',
					uid: '$uid'
				},
				create_time: {
					$min: '$create_time'
				}
			},
			sort: {
				create_time: 1
			},
			getAll: true
		})

		let res = {
			code: 0,
			msg: 'success'
		}
		// if (this.debug) {
		//   console.log('statRes', JSON.stringify(statRes))
		// }
		if (statRes.data.length > 0) {
			const uniCrypto = new UniCrypto()
			// 同应用、平台、渠道、版本的数据合并
			const statData = [];
			let statKey;
			let data

			for (const sti in statRes.data) {
				data = statRes.data[sti]
				statKey = uniCrypto.md5(data._id.appid + data._id.platform + data._id.version + data._id
					.channel)
				if (!statData[statKey]) {
					statData[statKey] = {
						appid: data._id.appid,
						platform: data._id.platform,
						version: data._id.version,
						channel: data._id.channel,
						uids: [],
						info: []
					}
					statData[statKey].uids.push(data._id.uid)
					statData[statKey].info[data._id.uid] = {
						create_time: data.create_time
					}
				} else {
					statData[statKey].uids.push(data._id.uid)
					statData[statKey].info[data._id.uid] = {
						create_time: data.create_time
					}
				}
			}

			this.fillData = []
			for (const sk in statData) {
				await this.getFillData(statData[sk])
			}

			if (this.fillData.length > 0) {
				res = await this.batchInsert(this.tableName, this.fillData)
			}
		}
		return res
	}

	async getFillData(data) {
		// 平台信息
		let platformInfo = null
		if (this.platforms && this.platforms[data.platform]) {
			platformInfo = this.platforms[data.platform]
		} else {
			const platform = new Platform()
			platformInfo = await platform.getPlatformAndCreate(data.platform, null)
			if (!platformInfo || platformInfo.length === 0) {
				platformInfo._id = ''
			}
			this.platforms[data.platform] = platformInfo
			if (this.debug) {
				console.log('platformInfo', JSON.stringify(platformInfo))
			}
		}

		// 渠道信息
		let channelInfo = null
		const channelKey = data.appid + '_' + platformInfo._id + '_' + data.channel
		if (this.channels && this.channels[channelKey]) {
			channelInfo = this.channels[channelKey]
		} else {
			const channel = new Channel()
			channelInfo = await channel.getChannelAndCreate(data.appid, platformInfo._id, data.channel)
			if (!channelInfo || channelInfo.length === 0) {
				channelInfo._id = ''
			}
			this.channels[channelKey] = channelInfo
			if (this.debug) {
				console.log('channelInfo', JSON.stringify(channelInfo))
			}
		}

		// 版本信息
		let versionInfo = null
		const versionKey = data.appid + '_' + data.platform + '_' + data.version
		if (this.versions && this.versions[versionKey]) {
			versionInfo = this.versions[versionKey]
		} else {
			const version = new Version()
			versionInfo = await version.getVersionAndCreate(data.appid, data.platform, data.version)
			if (!versionInfo || versionInfo.length === 0) {
				versionInfo._id = ''
			}
			this.versions[versionKey] = versionInfo
			if (this.debug) {
				console.log('versionInfo', JSON.stringify(versionInfo))
			}
		}

		// 是否在本周内已存在
		const datetime = new DateTime()
		const dateDimension = datetime.getTimeDimensionByType('week', 0, this.startTime)

		// 取出本周已经存储的uid
		const weekHaveUserList = []
		const haveWeekList = await this.selectAll(this.tableName, {
			appid: data.appid,
			version_id: versionInfo._id,
			platform_id: platformInfo._id,
			channel_id: channelInfo._id,
			uid: {
				$in: data.uids
			},
			dimension: 'week',
			create_time: {
				$gte: dateDimension.startTime,
				$lte: dateDimension.endTime
			}
		}, {
			uid: 1
		})

		if (this.debug) {
			console.log('haveWeekList', JSON.stringify(haveWeekList))
		}

		if (haveWeekList.data.length > 0) {
			for (const hui in haveWeekList.data) {
				weekHaveUserList.push(haveWeekList.data[hui].uid)
			}
		}

		// 取出本月已经存储的uid
		const dateMonthDimension = datetime.getTimeDimensionByType('month', 0, this.startTime)
		const monthHaveUserList = []
		const haveMonthList = await this.selectAll(this.tableName, {
			appid: data.appid,
			version_id: versionInfo._id,
			platform_id: platformInfo._id,
			channel_id: channelInfo._id,
			uid: {
				$in: data.uids
			},
			dimension: 'month',
			create_time: {
				$gte: dateMonthDimension.startTime,
				$lte: dateMonthDimension.endTime
			}
		}, {
			uid: 1
		})

		if (this.debug) {
			console.log('haveMonthList', JSON.stringify(haveMonthList))
		}

		if (haveMonthList.data.length > 0) {
			for (const hui in haveMonthList.data) {
				monthHaveUserList.push(haveMonthList.data[hui].uid)
			}
		}

		for (const ui in data.uids) {
			if (!weekHaveUserList.includes(data.uids[ui])) {
				this.fillData.push({
					appid: data.appid,
					platform_id: platformInfo._id,
					channel_id: channelInfo._id,
					version_id: versionInfo._id,
					uid: data.uids[ui],
					dimension: 'week',
					create_time: data.info[data.uids[ui]].create_time
				})
			}

			if (!monthHaveUserList.includes(data.uids[ui])) {
				this.fillData.push({
					appid: data.appid,
					platform_id: platformInfo._id,
					channel_id: channelInfo._id,
					version_id: versionInfo._id,
					uid: data.uids[ui],
					dimension: 'month',
					create_time: data.info[data.uids[ui]].create_time
				})
			}
		}

		return true
	}
	
	/**
	 * 日志清理，此处日志为临时数据并不需要自定义清理，默认为固定值即可
	 */
	async clean() {
		// 清除周数据，周留存统计最高需要10周数据，多余的为无用数据
		const weeks = 10
		console.log('Clean user\'s weekly logs - week:', weeks)

		const dateTime = new DateTime()

		const res = await this.delete(this.tableName, {
			dimension: 'week',
			create_time: {
				$lt: dateTime.getTimeBySetWeek(0 - weeks)
			}
		})

		if (!res.code) {
			console.log('Clean user\'s weekly logs - res:', res)
		}

		// 清除月数据，月留存统计最高需要10个月数据，多余的为无用数据
		const monthes = 10
		console.log('Clean user\'s monthly logs - month:', monthes)
		const monthRes = await this.delete(this.tableName, {
			dimension: 'month',
			create_time: {
				$lt: dateTime.getTimeBySetMonth(0 - monthes)
			}
		})
		if (!monthRes.code) {
			console.log('Clean user\'s monthly logs - res:', res)
		}
		return monthRes
	}
}
