import { Notes, Notifications } from "../../../../models/index.js";
import { PaginationHelpers } from "./pagination.js";
import { MastoApiError } from "../middleware/catch-errors.js";
export class NotificationHelpers {
    static async getNotifications(maxId, sinceId, minId, limit = 40, types, excludeTypes, accountId, ctx) {
        if (limit > 80) limit = 80;
        const user = ctx.user;
        let requestedTypes = types ? this.decodeTypes(types) : [
            'follow',
            'mention',
            'reply',
            'renote',
            'quote',
            'reaction',
            'pollEnded',
            'receiveFollowRequest'
        ];
        if (excludeTypes) {
            const excludedTypes = this.decodeTypes(excludeTypes);
            requestedTypes = requestedTypes.filter((p)=>!excludedTypes.includes(p));
        }
        const query = PaginationHelpers.makePaginationQuery(Notifications.createQueryBuilder("notification"), sinceId, maxId, minId).andWhere("notification.notifieeId = :userId", {
            userId: user.id
        }).andWhere("notification.type IN (:...types)", {
            types: requestedTypes
        });
        if (accountId !== undefined) query.andWhere("notification.notifierId = :notifierId", {
            notifierId: accountId
        });
        query.leftJoinAndSelect("notification.note", "note").leftJoinAndSelect("notification.notifier", "notifier").leftJoinAndSelect("notification.notifiee", "notifiee");
        return PaginationHelpers.execQueryLinkPagination(query, limit, minId !== undefined, ctx);
    }
    static async getNotification(id, ctx) {
        const user = ctx.user;
        return Notifications.findOneBy({
            id: id,
            notifieeId: user.id
        });
    }
    static async getNotificationOr404(id, ctx) {
        return this.getNotification(id, ctx).then((p)=>{
            if (p) return p;
            throw new MastoApiError(404);
        });
    }
    static async dismissNotification(id, ctx) {
        const user = ctx.user;
        await Notifications.update({
            id: id,
            notifieeId: user.id
        }, {
            isRead: true
        });
    }
    static async clearAllNotifications(ctx) {
        const user = ctx.user;
        await Notifications.update({
            notifieeId: user.id
        }, {
            isRead: true
        });
    }
    static async markConversationAsRead(id, ctx) {
        const user = ctx.user;
        const notesQuery = Notes.createQueryBuilder("note").select("note.id").andWhere("COALESCE(note.threadId, note.id) = :conversationId");
        await Notifications.createQueryBuilder("notification").where(`notification."noteId" IN (${notesQuery.getQuery()})`).andWhere(`notification."notifieeId" = :userId`).andWhere(`notification."isRead" = FALSE`).andWhere("notification.type IN (:...types)").setParameter("userId", user.id).setParameter("conversationId", id).setParameter("types", [
            'reply',
            'mention'
        ]).update().set({
            isRead: true
        }).execute();
    }
    static decodeTypes(types) {
        const result = [];
        if (types.includes('follow')) result.push('follow');
        if (types.includes('mention')) result.push('mention', 'reply');
        if (types.includes('reblog')) result.push('renote', 'quote');
        if (types.includes('favourite')) result.push('reaction');
        if (types.includes('poll')) result.push('pollEnded');
        if (types.includes('follow_request')) result.push('receiveFollowRequest');
        return result;
    }
}
