import ItemsService from "./ItemsService.js";
import { db } from "../utils/db.js";
import { schemaManager } from "../utils/schemaManager.js";
import { APIError } from "../utils/errorHandler.js";
import { eq, and, lt, inArray } from "drizzle-orm";
import { invalidateEntireCache } from "./CacheService.js";
class NotificationService {
    accountability;
    itemsService;
    constructor(params = {}) {
        const { accountability } = params;
        this.accountability = accountability;
        this.itemsService = new ItemsService("baasix_Notification", { accountability });
    }
    /**
     * Send notifications to multiple users
     */
    async send(options) {
        const { type, title, message, data, userIds, tenant_Id } = options;
        if (!type || !title || !message || !Array.isArray(userIds) || userIds.length === 0) {
            throw new APIError("Invalid notification parameters", 400);
        }
        try {
            // Start a transaction
            return await db.transaction(async (tx) => {
                const notifications = [];
                // Create notifications for each user
                for (const userId of userIds) {
                    const notificationData = {
                        type,
                        title,
                        message,
                        data,
                        userId,
                        seen: false,
                        tenant_Id: tenant_Id || null,
                    };
                    // Use ItemsService to create notification with transaction
                    // bypassPermissions: true since this is a system operation
                    const itemsServiceWithTx = new ItemsService("baasix_Notification", {
                        accountability: this.accountability,
                    });
                    const notificationId = await itemsServiceWithTx.createOne(notificationData, {
                        bypassPermissions: true,
                    });
                    notifications.push(notificationId);
                }
                // Invalidate cache after transaction commits
                await invalidateEntireCache("baasix_Notification");
                return notifications;
            });
        }
        catch (error) {
            throw new APIError("Error sending notifications", 500, error.message);
        }
    }
    /**
     * Mark notifications as seen for a user
     */
    async markAsSeen(userId, notificationIds = null) {
        try {
            const notificationTable = schemaManager.getTable("baasix_Notification");
            let whereConditions;
            if (notificationIds && notificationIds.length > 0) {
                whereConditions = and(eq(notificationTable.userId, userId), eq(notificationTable.seen, false), inArray(notificationTable.id, notificationIds));
            }
            else {
                whereConditions = and(eq(notificationTable.userId, userId), eq(notificationTable.seen, false));
            }
            const result = await db
                .update(notificationTable)
                .set({ seen: true, seenAt: new Date() })
                .where(whereConditions);
            // Invalidate cache after update
            await invalidateEntireCache("baasix_Notification");
            return result.rowCount || 0;
        }
        catch (error) {
            throw new APIError("Error marking notifications as seen", 500, error.message);
        }
    }
    /**
     * Mark notifications as unseen (unread) for a user.
     * Mirrors markAsSeen: omitting notificationIds marks ALL of the user's
     * seen notifications as unseen again.
     */
    async markAsUnseen(userId, notificationIds = null) {
        try {
            const notificationTable = schemaManager.getTable("baasix_Notification");
            let whereConditions;
            if (notificationIds && notificationIds.length > 0) {
                whereConditions = and(eq(notificationTable.userId, userId), eq(notificationTable.seen, true), inArray(notificationTable.id, notificationIds));
            }
            else {
                whereConditions = and(eq(notificationTable.userId, userId), eq(notificationTable.seen, true));
            }
            // markAsSeen sets seenAt unconditionally; clear it the same way.
            const result = await db
                .update(notificationTable)
                .set({ seen: false, seenAt: null })
                .where(whereConditions);
            // Invalidate cache after update
            await invalidateEntireCache("baasix_Notification");
            return result.rowCount || 0;
        }
        catch (error) {
            throw new APIError("Error marking notifications as unseen", 500, error.message);
        }
    }
    /**
     * Delete notifications for a user
     */
    async deleteForUser(userId, notificationIds = null) {
        try {
            const notificationTable = schemaManager.getTable("baasix_Notification");
            let whereConditions;
            if (notificationIds && notificationIds.length > 0) {
                whereConditions = and(eq(notificationTable.userId, userId), inArray(notificationTable.id, notificationIds));
            }
            else {
                whereConditions = eq(notificationTable.userId, userId);
            }
            const result = await db
                .delete(notificationTable)
                .where(whereConditions);
            // Invalidate cache after delete
            await invalidateEntireCache("baasix_Notification");
            return result.rowCount || 0;
        }
        catch (error) {
            throw new APIError("Error deleting notifications", 500, error.message);
        }
    }
    /**
     * Get unread notifications count for a user
     */
    async getUnreadCount(userId) {
        try {
            // Use ItemsService.readByQuery to count
            // bypassPermissions: true since users should always be able to see their own notification count
            const result = await this.itemsService.readByQuery({
                filter: {
                    userId: userId,
                    seen: false,
                },
                limit: -1, // Get all to count
            }, true);
            return result.data.length;
        }
        catch (error) {
            throw new APIError("Error getting unread count", 500, error.message);
        }
    }
    /**
     * Get user's notifications with pagination and filtering
     * bypassPermissions: true since the route already ensures users can only see their own notifications
     */
    async getUserNotifications(query = {}) {
        try {
            return await this.itemsService.readByQuery(query, true);
        }
        catch (error) {
            throw new APIError("Error fetching notifications", 500, error.message);
        }
    }
    /**
     * Delete old notifications based on age
     */
    async cleanupOldNotifications(days = 30) {
        try {
            const notificationTable = schemaManager.getTable("baasix_Notification");
            const cutoffDate = new Date();
            cutoffDate.setDate(cutoffDate.getDate() - days);
            const result = await db
                .delete(notificationTable)
                .where(lt(notificationTable.createdAt, cutoffDate));
            // Invalidate cache after cleanup
            await invalidateEntireCache("baasix_Notification");
            return result.rowCount || 0;
        }
        catch (error) {
            throw new APIError("Error cleaning up old notifications", 500, error.message);
        }
    }
}
export default NotificationService;
//# sourceMappingURL=NotificationService.js.map