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

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

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

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

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

	const curatedUser = {
		id: user.id,
		username: user.username,
		email: user.email,
		emailVerified: user.email_verified,
		identityVerified: user.identity_verified,
		avatar: `/media/avatars/${user.id}_${user.username}.png`,
		role: user.role,
		createdAt: user.created_at,
	};

	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) {
	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) {
		throw new HttpError(`User '${userId}' not found`, 404);
	}

	/*
	const [stashes, templates] = await Promise.all([
		knex('stashes')
			.select('stashes.*', 'stashes_meta.*')
			.leftJoin('stashes_meta', 'stashes_meta.stash_id', 'stashes.id')
			.where('user_id', user.id)
			.modify((builder) => {
				if (reqUser?.id !== user.id && !options.includeStashes) {
					builder.where('public', true);
				}
			}),
		options.includeTemplates
			? knex('users_templates').where('user_id', user.id)
			: null,
	]);
	*/

	if (options.raw) {
		// return { user, stashes, templates };
		return { user };
	}

	// return curateUser(user, { stashes, templates });
	return curateUser(user, {});
}

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) {
	console.log(ban);

	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);
}