import config from 'config';
import { parse } from 'yaml';

// import { curateStash } from './stashes.js';
import { HttpError } from './errors.js';
import { knexOwner as knex } from './knex.js';

function curateTemplate(template) {
	return {
		id: template.id,
		name: template.name,
		template: template.template,
		createdAt: template.created_at,
	};
}

export function curateUser(user, reqUser, options = {}) {
	if (!user) {
		return null;
	}

	// const curatedStashes = assets.stashes?.filter(Boolean).map((stash) => curateStash(stash)) || [];

	const privateUser = {
		email: user.email,
		settings: user.settings,
	};

	const curatedUser = {
		id: user.id,
		username: user.username,
		isEmailVerified: user.email_verified,
		isIdentityVerified: user.identity_verified,
		avatar: `/media/avatars/${user.id}_${user.username}.png`,
		role: user.role,
		abilities: [...user.role_abilities || [], ...user.abilities || []],
		createdAt: user.created_at,
		...(reqUser?.id === user.id || options.includePrivate ? privateUser : null),
	};

	return curatedUser;
}

function whereUser(builder, userId, options = {}) {
	if (Number.isNaN(Number(userId))) {
		builder.where(knex.raw('lower(users.username)'), userId.toLowerCase());

		if (options.email) {
			builder.orWhere(knex.raw('lower(users.email)'), userId.toLowerCase());
		}

		return;
	}

	builder.where('users.id', Number(userId));
}

export async function fetchUser(userId, options = {}, reqUser) {
	if (!userId) {
		if (options.raw) {
			return { user: null };
		}

		return null;
	}

	const user = await knex('users')
		.select(knex.raw('users.*, users_roles.abilities as role_abilities'))
		.modify((builder) => whereUser(builder, userId, options))
		.leftJoin('users_roles', 'users_roles.role', 'users.role')
		.groupBy('users.id', 'users_roles.role')
		.first();

	if (!user && options.throwError !== false) {
		throw new HttpError(`User '${userId}' not found`, 404);
	}

	if (options.raw) {
		return { user };
	}

	return curateUser(user, reqUser, options);
}

export async function fetchUserTemplates(reqUser) {
	const templates = await knex('users_templates')
		.where('user_id', reqUser.id)
		.orderBy('created_at', 'asc');

	return templates.map((template) => curateTemplate(template));
}

export async function createTemplate(template, reqUser) {
	if (!template.template) {
		throw new HttpError('No template specified', 400);
	}

	if (!template.name) {
		throw new HttpError('No template name specified', 400);
	}

	try {
		parse(template.template);
	}
	catch (error) {
		throw new HttpError(`Invalid YAML: ${error.message}`, 400);
	}

	const [templateEntry] = await knex('users_templates')
		.insert({
			user_id: reqUser.id,
			name: template.name,
			template: template.template,
		})
		.onConflict(['name', 'user_id'])
		.merge()
		.returning('*');

	return curateTemplate(templateEntry);
}

export async function removeTemplate(templateId, reqUser) {
	await knex('users_templates')
		.where('id', templateId)
		.where('user_id', reqUser.id)
		.delete();
}

export async function createBan(ban, reqUser) {
	if (reqUser.role !== 'admin') {
		throw new HttpError('You do not have sufficient privileges to set a ban', 403);
	}

	const targetUser = ban.userId && await knex('users').where('id', ban.userId).first();

	const curatedBan = {
		user_id: ban.userId,
		username: ban.username,
		ip: ban.banIp && targetUser.last_ip,
		expires_at: knex.raw('now() + make_interval(mins => :minutes)', { minutes: config.bans.defaultExpiry }),
	};

	await knex('bans').insert(curatedBan);
}
