import rndstr from "rndstr";
import type { Note } from "@/models/entities/note.js";
import type { User } from "@/models/entities/user.js";
import { Notes, UserProfiles, NoteReactions } from "@/models/index.js";
import { generateMutedUserQuery } from "./generate-muted-user-query.js";
import { generateBlockedUserQuery } from "./generate-block-query.js";

// TODO: リアクション、Renote、返信などをしたノートは除外する

export async function injectFeatured(timeline: Note[], user?: User | null) {
	if (timeline.length < 5) return;

	if (user) {
		const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
		if (!profile.injectFeaturedNote) return;
	}

	const max = 30;
	const day = 1000 * 60 * 60 * 24 * 3; // 3日前まで

	const query = Notes.createQueryBuilder("note")
		.addSelect("note.score")
		.where("note.userHost IS NULL")
		.andWhere("note.score > 0")
		.andWhere("note.createdAt > :date", { date: new Date(Date.now() - day) })
		.andWhere(`note.visibility = 'public'`)
		.innerJoinAndSelect("note.user", "user");

	if (user) {
		query.andWhere("note.userId != :userId", { userId: user.id });

		generateMutedUserQuery(query, user);
		generateBlockedUserQuery(query, user);

		const reactionQuery = NoteReactions.createQueryBuilder("reaction")
			.select("reaction.noteId")
			.where("reaction.userId = :userId", { userId: user.id });

		query.andWhere(`note.id NOT IN (${reactionQuery.getQuery()})`);
	}

	const notes = await query.orderBy("note.score", "DESC").take(max).getMany();

	if (notes.length === 0) return;

	// Pick random one
	const featured = notes[Math.floor(Math.random() * notes.length)];

	(featured as any)._featuredId_ = rndstr("a-z0-9", 8);

	// Inject featured
	timeline.splice(3, 0, featured);
}
