const express = require("express"),
	router = express.Router(),
	Discord = require("discord.js");

const fetch = require("node-fetch"),
	btoa = require("btoa");

// Gets login page
router.get("/login", async function(req, res) {
	if (!req.user || !req.user.id || !req.user.guilds) return res.redirect(`https://discordapp.com/api/oauth2/authorize?client_id=${req.client.user.id}&scope=identify%20guilds&response_type=code&redirect_uri=${encodeURIComponent(`${req.client.config.dashboard.baseURL}/api/callback`)}&state=${req.query.state || "no"}`);

	res.redirect("/selector");
});

router.get("/callback", async (req, res) => {
	if (!req.query.code) return res.redirect(req.client.config.dashboard.failureURL);
	if (req.query.state && req.query.state.startsWith("invite")) {
		if (req.query.code) {
			const guildID = req.query.state.substr("invite".length, req.query.state.length);
			req.client.knownGuilds.push({ id: guildID, user: req.user.id });

			return res.redirect(`/manage/${guildID}`);
		}
	}

	const redirectURL = req.client.states[req.query.state] || "/selector";
	const params = new URLSearchParams();
	params.set("grant_type", "authorization_code");
	params.set("code", req.query.code);
	params.set("redirect_uri", `${req.client.config.dashboard.baseURL}/api/callback`);
	let response = await fetch("https://discord.com/api/oauth2/token", {
		method: "POST",
		body: params.toString(),
		headers: {
			Authorization: `Basic ${btoa(`${req.client.user.id}:${req.client.config.dashboard.secret}`)}`,
			"Content-Type": "application/x-www-form-urlencoded"
		}
	});

	// Fetch tokens (used to fetch user informations)
	const tokens = await response.json();

	// If the code isn't valid
	if (tokens.error || !tokens.access_token) return res.redirect(`/api/login&state=${req.query.state}`);
	const userData = {
		infos: null,
		guilds: null
	};
	while (!userData.infos || !userData.guilds) {
		/* User infos */
		if (!userData.infos) {
			response = await fetch("http://discordapp.com/api/users/@me", {
				method: "GET",
				headers: { Authorization: `Bearer ${tokens.access_token}` }
			});
			const json = await response.json();
			if (json.retry_after) await req.client.wait(json.retry_after);
			else userData.infos = json;
		}

		/* User guilds */
		if (!userData.guilds) {
			response = await fetch("https://discordapp.com/api/users/@me/guilds", {
				method: "GET",
				headers: { Authorization: `Bearer ${tokens.access_token}` }
			});
			const json = await response.json();
			if (json.retry_after) await req.client.wait(json.retry_after);
			else userData.guilds = json;
		}
	}

	/* Change format (from "0": { data }, "1": { data }, etc... to [ { data }, { data } ]) */
	const guilds = [];
	for (const guildPos in userData.guilds) guilds.push(userData.guilds[guildPos]);

	// Update session
	req.session.user = { ... userData.infos, ... { guilds } };
	const user = await req.client.users.fetch(req.session.user.id);
	const userDB = await req.client.findOrCreateUser(req.session.user.id);
	const logsChannel = req.client.channels.cache.get(req.client.config.dashboard.logs);
	if (!userDB.logged && logsChannel && user) {
		const embed = new Discord.MessageEmbed()
			.setAuthor({ name: user.username, iconURL: user.displayAvatarURL() })
			.setColor(req.client.config.embed.color)
			.setDescription(req.client.translate("dashboard:FIRST_LOGIN", { user: user.tag }));
		logsChannel.send({ embeds: [embed] });
		userDB.logged = true;
		userDB.save();
	}
	res.redirect(redirectURL);
});

module.exports = router;