'use strict';

const nconf = require('nconf');
const _ = require('lodash');

const db = require('../../database');
const user = require('../../user');
const posts = require('../../posts');
const categories = require('../../categories');
const meta = require('../../meta');
const privileges = require('../../privileges');
const accountHelpers = require('./helpers');
const helpers = require('../helpers');
const utils = require('../../utils');

const profileController = module.exports;

profileController.get = async function (req, res, next) {
	const lowercaseSlug = req.params.userslug.toLowerCase();

	if (req.params.userslug !== lowercaseSlug) {
		if (res.locals.isAPI) {
			req.params.userslug = lowercaseSlug;
		} else {
			return res.redirect(`${nconf.get('relative_path')}/user/${lowercaseSlug}`);
		}
	}

	const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, req.query);
	if (!userData) {
		return next();
	}

	await incrementProfileViews(req, userData);

	const [latestPosts, bestPosts] = await Promise.all([
		getLatestPosts(req.uid, userData),
		getBestPosts(req.uid, userData),
		posts.parseSignature(userData, req.uid),
	]);

	if (meta.config['reputation:disabled']) {
		delete userData.reputation;
	}

	userData.posts = latestPosts; // for backwards compat.
	userData.latestPosts = latestPosts;
	userData.bestPosts = bestPosts;
	userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username }]);
	userData.title = userData.username;
	userData.allowCoverPicture = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:cover-picture'];

	// Show email changed modal on first access after said change
	userData.emailChanged = req.session.emailChanged;
	delete req.session.emailChanged;

	if (!userData.profileviews) {
		userData.profileviews = 1;
	}

	addMetaTags(res, userData);

	userData.selectedGroup = userData.groups.filter(group => group && userData.groupTitleArray.includes(group.name))
		.sort((a, b) => userData.groupTitleArray.indexOf(a.name) - userData.groupTitleArray.indexOf(b.name));

	res.render('account/profile', userData);
};

async function incrementProfileViews(req, userData) {
	if (req.uid >= 1) {
		req.session.uids_viewed = req.session.uids_viewed || {};

		if (
			req.uid !== userData.uid &&
			(!req.session.uids_viewed[userData.uid] || req.session.uids_viewed[userData.uid] < Date.now() - 3600000)
		) {
			await user.incrementUserFieldBy(userData.uid, 'profileviews', 1);
			req.session.uids_viewed[userData.uid] = Date.now();
		}
	}
}

async function getLatestPosts(callerUid, userData) {
	return await getPosts(callerUid, userData, 'pids');
}

async function getBestPosts(callerUid, userData) {
	return await getPosts(callerUid, userData, 'pids:votes');
}

async function getPosts(callerUid, userData, setSuffix) {
	const cids = await categories.getCidsByPrivilege('categories:cid', callerUid, 'topics:read');
	const keys = cids.map(c => `cid:${c}:uid:${userData.uid}:${setSuffix}`);
	let hasMorePosts = true;
	let start = 0;
	const count = 10;
	const postData = [];

	const [isAdmin, isModOfCids, canSchedule] = await Promise.all([
		user.isAdministrator(callerUid),
		user.isModerator(callerUid, cids),
		privileges.categories.isUserAllowedTo('topics:schedule', cids, callerUid),
	]);
	const cidToIsMod = _.zipObject(cids, isModOfCids);
	const cidToCanSchedule = _.zipObject(cids, canSchedule);

	do {
		/* eslint-disable no-await-in-loop */
		const pids = await db.getSortedSetRevRange(keys, start, start + count - 1);
		if (!pids.length || pids.length < count) {
			hasMorePosts = false;
		}
		if (pids.length) {
			const p = await posts.getPostSummaryByPids(pids, callerUid, { stripTags: false });
			postData.push(...p.filter(
				p => p && p.topic && (isAdmin || cidToIsMod[p.topic.cid] ||
					(p.topic.scheduled && cidToCanSchedule[p.topic.cid]) || (!p.deleted && !p.topic.deleted))
			));
		}
		start += count;
	} while (postData.length < count && hasMorePosts);
	return postData.slice(0, count);
}

function addMetaTags(res, userData) {
	const plainAboutMe = userData.aboutme ? utils.stripHTMLTags(utils.decodeHTMLEntities(userData.aboutme)) : '';
	res.locals.metaTags = [
		{
			name: 'title',
			content: userData.fullname || userData.username,
			noEscape: true,
		},
		{
			name: 'description',
			content: plainAboutMe,
		},
		{
			property: 'og:title',
			content: userData.fullname || userData.username,
			noEscape: true,
		},
		{
			property: 'og:description',
			content: plainAboutMe,
		},
	];

	if (userData.picture) {
		res.locals.metaTags.push(
			{
				property: 'og:image',
				content: userData.picture,
				noEscape: true,
			},
			{
				property: 'og:image:url',
				content: userData.picture,
				noEscape: true,
			}
		);
	}
}
