async function query(sql, args) {
	let rows = [];
	await ssb.sqlAsync(sql, args ?? [], function (row) {
		rows.push(row);
	});
	return rows;
}

async function get_biggest() {
	return query(`
		select author, sum(length(content)) as size from messages group by author order by size desc limit 10;
	`);
}

async function get_total() {
	return (
		await query(`
		select sum(length(content)) as size, count(distinct author) as count from messages;
	`)
	)[0];
}

async function get_names(identities) {
	return query(
		`
		SELECT author, name FROM (
			SELECT
				messages.author,
				RANK() OVER (PARTITION BY messages.author ORDER BY messages.sequence DESC) AS author_rank,
				messages.content ->> 'name' AS name
			FROM messages
			JOIN json_each(?) AS identities ON identities.value = messages.author
			WHERE
				json_extract(messages.content, '$.type') = 'about' AND
				content ->> 'about' = messages.author AND name IS NOT NULL)
		WHERE author_rank = 1
	`,
		[JSON.stringify(identities)]
	);
}

async function get_most_follows() {
	return query(`
		select author, count(*) as count
		from messages
		where content ->> 'type' = 'contact' and content ->> 'following' = true
		group by author
		order by count desc
		limit 10;
	`);
}

function nice_size(bytes) {
	let value = bytes;
	let index = 0;
	let units = ['B', 'kB', 'MB', 'GB'];
	while (value > 1024 && index < units.length - 1) {
		value /= 1024;
		index++;
	}
	return `${Math.round(value * 10) / 10} ${units[index]}`;
}

async function main() {
	await app.setDocument(
		'<p style="color: #fff">Finding the top 10 largest feeds...</p>'
	);
	let most_follows = await get_most_follows();
	let total = await get_total();
	let identities = await ssb.getAllIdentities();
	let following1 = await ssb.following(identities, 1);
	let following2 = await ssb.following(identities, 2);
	let biggest = await get_biggest();
	let names = await get_names(
		[].concat(
			biggest.map((x) => x.author),
			most_follows.map((x) => x.author)
		)
	);
	names = Object.fromEntries(names.map((x) => [x.author, x.name]));
	for (let item of biggest) {
		item.name = names[item.author];
		item.following =
			identities.indexOf(item.author) != -1
				? 0
				: following1[item.author] !== undefined
					? 1
					: following2[item.author] !== undefined
						? 2
						: undefined;
	}
	for (let item of most_follows) {
		item.name = names[item.author];
	}
	let html = `<body style="color: #000; background-color: #ddd">\n
		<h1>Storage Summary</h1>
		<h2>Top 10 Accounts by Size</h2>
		<ol>`;
	for (let item of biggest) {
		html += `<li>
			<span style="color: #888">${nice_size(item.size)}</span>
			<a target="_top" href="/~core/ssb/#${encodeURI(item.author)}">${item.name ?? item.author}</a>
		</li>
		\n`;
	}
	html += `
		</ol>
		<h2>Top 10 Accounts by Follows</h2>
		<ol>`;
	for (let item of most_follows) {
		html += `<li>
			<span style="color: #888">${item.count}</span>
			${following2[item.author] ? '✅' : '🚫'}
			<a target="_top" href="/~core/ssb/#${encodeURI(item.author)}">${item.name ?? item.author}</a>
		</li>
		\n`;
	}
	html += `
		</ol>
		<p>Total <span style="color: #888">${nice_size(total.size)}</span> in ${total.count} accounts.</p>
	`;
	await app.setDocument(html);
}

main().catch(function (e) {
	print(e);
});
