import webpush from 'web-push';
import db from '../../database/models/index.js';
import { getIO } from './socket.js';
import logger from './logger.js';

const { Notification, PushSubscription } = db;

// Initialize VAPID keys
if (process.env.VAPID_PUBLIC_KEY && process.env.VAPID_PRIVATE_KEY) {
    webpush.setVapidDetails(
        `mailto:${process.env.VAPID_EMAIL || 'admin@royalenfield.com'}`,
        process.env.VAPID_PUBLIC_KEY,
        process.env.VAPID_PRIVATE_KEY
    );
}

/**
 * Sends a notification to a specific user via multiple channels.
 */
export const sendNotification = async (params: {
    userId: string;
    title: string;
    message: string;
    type?: string;
    link?: string;
    data?: any;
}) => {
    const { userId, title, message, type = 'info', link, data } = params;
    logger.info(`Starting sendNotification for user: ${userId}`);

    try {
        // 1. Create In-App Notification (Database)
        const notification = await Notification.create({
            userId,
            title,
            message,
            type,
            link,
            isRead: false
        });
        logger.info(`Notification created in DB with ID: ${notification.id}`);

        // 2. Real-time update via Socket.io
        try {
            const io = getIO();
            const roomName = `user_${userId}`;
            logger.info(`Emitting real-time notification to room: ${roomName}`);

            // Emit to a private room for the user
            io.to(roomName).emit('notification', {
                id: notification.id,
                title,
                message,
                type,
                link,
                createdAt: notification.createdAt
            });
        } catch (socketError: any) {
            logger.warn(`Socket.io emit failed: ${socketError.message}`);
        }

        // 3. Web Push Notification
        const subscriptions = await PushSubscription.findAll({ where: { userId } });

        for (const sub of subscriptions) {
            try {
                const pushConfig = {
                    endpoint: sub.endpoint,
                    keys: {
                        p256dh: sub.p256dh,
                        auth: sub.auth
                    }
                };

                const payload = JSON.stringify({
                    title,
                    body: message,
                    icon: '/re-logo.png', // Fallback icon path
                    data: {
                        url: link || '/',
                        ...data
                    }
                });

                await webpush.sendNotification(pushConfig, payload);
            } catch (error: any) {
                logger.error(`Error sending Web Push to subscription ${sub.id}:`, error.message);
                // If subscription is expired or invalid, remove it
                if (error.statusCode === 410 || error.statusCode === 404) {
                    await sub.destroy();
                    logger.info(`Removed invalid push subscription: ${sub.id}`);
                }
            }
        }

        return notification;
    } catch (error) {
        logger.error('Error in sendNotification:', error);
        throw error;
    }
};

/**
 * Notifies multiple users (e.g., participants in a request).
 */
export const notifyUsers = async (userIds: string[], params: any) => {
    return Promise.all(userIds.map(userId => sendNotification({ ...params, userId })));
};
