import rndstr from "rndstr";
import { PromoReads, PromoNotes, Notes, Users } from "../../../models/index.js";
import { shouldHideEUsersFor } from "./generate-minor-badge-visibility-query.js";
import { readPromo } from "./read-promo.js";
const systemTags = new Set([
    "adservice",
    "videoservice",
    "audioservice",
    "imageservice",
    "karaokeservice",
    "lua4frozen"
]);
function isExplicitAd(note) {
    return note.tags.includes("explicit") || note.user?.minorBadges?.includes("E") === true;
}
export async function injectPromo(timeline, user, preferredTag) {
    // TODO: readやexpireフィルタはクエリ側でやる
    const readDay = new Date().toISOString().slice(0, 10);
    const reads = user ? await PromoReads.findBy({
        userId: user.id,
        readDay
    }) : [];
    let promos = await PromoNotes.find();
    promos = promos.filter((n)=>n.expiresAt.getTime() > Date.now());
    promos = promos.filter((n)=>n.remainingCredits > 0);
    promos = promos.filter((n)=>!reads.map((r)=>r.noteId).includes(n.noteId));
    if (promos.length === 0) return;
    const candidates = [];
    for (const promo of promos){
        const note = await Notes.findOneBy({
            id: promo.noteId
        });
        if (!note?.tags.includes("adservice")) continue;
        note.user = await Users.findOneByOrFail({
            id: note.userId
        });
        if (user && shouldHideEUsersFor(user) && isExplicitAd(note)) continue;
        candidates.push(note);
    }
    if (candidates.length === 0) return;
    const normalizedPreferredTag = preferredTag?.trim().toLowerCase().replace(/^#/, "");
    const priority = normalizedPreferredTag && !systemTags.has(normalizedPreferredTag) ? candidates.filter((note)=>note.tags.includes(normalizedPreferredTag)) : [];
    const pool = priority.length > 0 ? priority : candidates;
    // Pick random promo
    const note = pool[Math.floor(Math.random() * pool.length)];
    const promo = promos.find((promo)=>promo.noteId === note.id);
    note._prId_ = rndstr("a-z0-9", 8);
    if (user && promo) {
        await readPromo(note, promo, user);
    }
    // Inject promo
    timeline.splice(Math.min(3, timeline.length), 0, note);
}
