// utils/notificationService.js
const Notification = require('../models/notification.model');
const Account = require('../models/account.model');
const admin = require('firebase-admin');

class NotificationService {
  static async sendNotification(userId, title, message, type, data = {}) {
    try {
      const notification = await Notification.create({
        user: userId,
        title,
        message,
        type,
        data,
        isRead: false,
        sentAt: new Date()
      });

      // Send push notification if user has FCM token
      const user = await Account.findById(userId).select('fcmToken pushNotificationsEnabled');
      
      if (user && user.pushNotificationsEnabled && user.fcmToken) {
        await this.sendPushNotification(user.fcmToken, title, message, {
          type,
          notificationId: notification._id.toString(),
          ...data
        });
      }

      return notification;
    } catch (error) {
      console.error('Error sending notification:', error);
      throw error;
    }
  }

  static async sendBulkNotifications(userIds, title, message, type, data = {}) {
    const notifications = [];
    
    for (const userId of userIds) {
      try {
        const notification = await this.sendNotification(
          userId,
          title,
          message,
          type,
          data
        );
        notifications.push(notification);
      } catch (error) {
        console.error(`Failed to send notification to user ${userId}:`, error);
      }
    }

    return notifications;
  }

  static async getUserNotifications(userId, page = 1, limit = 20, unreadOnly = false) {
    const skip = (page - 1) * limit;
    
    const query = { user: userId };
    if (unreadOnly) {
      query.isRead = false;
    }

    const [notifications, total] = await Promise.all([
      Notification.find(query)
        .sort({ createdAt: -1 })
        .skip(skip)
        .limit(limit)
        .lean(),
      Notification.countDocuments(query)
    ]);

    const unreadCount = await Notification.countDocuments({
      user: userId,
      isRead: false
    });

    const totalPages = Math.ceil(total / limit);

    return {
      notifications,
      unreadCount,
      pagination: {
        totalItems: total,
        totalPages,
        currentPage: page,
        itemsPerPage: limit,
        hasNextPage: page < totalPages,
        hasPreviousPage: page > 1
      }
    };
  }

  static async markAsRead(notificationId, userId) {
    const notification = await Notification.findOneAndUpdate(
      {
        _id: notificationId,
        user: userId
      },
      {
        isRead: true,
        readAt: new Date()
      },
      { new: true }
    );

    if (!notification) {
      throw new Error('Notification not found');
    }

    return notification;
  }

  static async markAllAsRead(userId) {
    await Notification.updateMany(
      { user: userId, isRead: false },
      {
        isRead: true,
        readAt: new Date()
      }
    );
  }

  static async sendPushNotification(fcmToken, title, body, data = {}) {
    try {
      if (!admin.apps.length) {
        // Initialize Firebase Admin if not already initialized
        admin.initializeApp({
          credential: admin.credential.cert({
            projectId: process.env.FIREBASE_PROJECT_ID,
            clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
            privateKey: process.env.FIREBASE_PRIVATE_KEY?.replace(/\\n/g, '\n')
          })
        });
      }

      const message = {
        notification: { title, body },
        data: Object.fromEntries(
          Object.entries(data).map(([key, value]) => [key, String(value)])
        ),
        token: fcmToken
      };

      const response = await admin.messaging().send(message);
      return response;
    } catch (error) {
      console.error('Error sending push notification:', error);
      // Don't throw - push notification failure shouldn't break the main flow
    }
  }
}

module.exports = NotificationService;