const NotificationService = require('../utils/notificationService');
const Account = require('../models/account.model');
const Notification = require('../models/notification.model');
const mongoose = require('mongoose');

class NotificationController {
  static async getUserNotifications(req, res) {
    try {
      const { id: userId } = req.user;
      const page = parseInt(req.query.page) || 1;
      const limit = parseInt(req.query.limit) || 20;
      const unreadOnly = req.query.unreadOnly === 'true';

      if (!mongoose.Types.ObjectId.isValid(userId)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid user ID format',
        });
      }

      const result = await NotificationService.getUserNotifications(
        userId,
        page,
        limit,
        unreadOnly
      );

      return res.status(200).json({
        success: true,
        data: result,
      });
    } catch (error) {
      console.error('Error fetching notifications:', error);
      return res.status(500).json({
        success: false,
        message: 'Internal server error',
        error: error.message,
      });
    }
  }

  static async markAsRead(req, res) {
    try {
      const { notificationId } = req.params;
      const { id: userId } = req.user;

      if (!mongoose.Types.ObjectId.isValid(notificationId)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid notification ID format',
        });
      }

      if (!mongoose.Types.ObjectId.isValid(userId)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid user ID format',
        });
      }

      const notification = await NotificationService.markAsRead(
        notificationId,
        userId
      );

      return res.status(200).json({
        success: true,
        message: 'Notification marked as read',
        data: notification,
      });
    } catch (error) {
      console.error('Error marking notification as read:', error);
      return res.status(500).json({
        success: false,
        message: 'Internal server error',
        error: error.message,
      });
    }
  }

  static async markAllAsRead(req, res) {
    try {
      const { id: userId } = req.user;

      if (!mongoose.Types.ObjectId.isValid(userId)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid user ID format',
        });
      }

      await NotificationService.markAllAsRead(userId);

      return res.status(200).json({
        success: true,
        message: 'All notifications marked as read',
      });
    } catch (error) {
      console.error('Error marking all notifications as read:', error);
      return res.status(500).json({
        success: false,
        message: 'Internal server error',
        error: error.message,
      });
    }
  }

  static async updateFCMToken(req, res) {
    try {
      const { id: userId } = req.user;
      const { fcmToken } = req.body;

      if (!mongoose.Types.ObjectId.isValid(userId)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid user ID format',
        });
      }

      if (!fcmToken) {
        return res.status(400).json({
          success: false,
          message: 'FCM token is required',
        });
      }

      const user = await Account.findById(userId);
      if (!user) {
        return res.status(404).json({
          success: false,
          message: 'User not found',
        });
      }

      user.fcmToken = fcmToken;
      await user.save();

      return res.status(200).json({
        success: true,
        message: 'FCM token updated successfully',
      });
    } catch (error) {
      console.error('Error updating FCM token:', error);
      return res.status(500).json({
        success: false,
        message: 'Internal server error',
        error: error.message,
      });
    }
  }

  static async deleteNotification(req, res) {
    try {
      const { notificationId } = req.params;
      const { id: userId } = req.user;

      if (!mongoose.Types.ObjectId.isValid(notificationId)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid notification ID format',
        });
      }

      if (!mongoose.Types.ObjectId.isValid(userId)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid user ID format',
        });
      }

      const notification = await Notification.findOne({
        _id: notificationId,
        user: userId,
      });

      if (!notification) {
        return res.status(404).json({
          success: false,
          message: 'Notification not found',
        });
      }

      await notification.deleteOne();

      return res.status(200).json({
        success: true,
        message: 'Notification deleted successfully',
      });
    } catch (error) {
      console.error('Error deleting notification:', error);
      return res.status(500).json({
        success: false,
        message: 'Internal server error',
        error: error.message,
      });
    }
  }

  static async getUnreadCount(req, res) {
    try {
      const { id: userId } = req.user;

      if (!mongoose.Types.ObjectId.isValid(userId)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid user ID format',
        });
      }

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

      return res.status(200).json({
        success: true,
        data: { unreadCount: count },
      });
    } catch (error) {
      console.error('Error fetching unread count:', error);
      return res.status(500).json({
        success: false,
        message: 'Internal server error',
        error: error.message,
      });
    }
  }

  static async updateNotificationPreferences(req, res) {
    try {
      const { id: userId } = req.user;
      const { emailNotifications, pushNotifications } = req.body;

      if (!mongoose.Types.ObjectId.isValid(userId)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid user ID format',
        });
      }

      const user = await Account.findById(userId);
      if (!user) {
        return res.status(404).json({
          success: false,
          message: 'User not found',
        });
      }

      user.emailNotificationsEnabled =
        emailNotifications !== undefined
          ? emailNotifications
          : user.emailNotificationsEnabled;
      user.pushNotificationsEnabled =
        pushNotifications !== undefined
          ? pushNotifications
          : user.pushNotificationsEnabled;
      await user.save();

      return res.status(200).json({
        success: true,
        message: 'Notification preferences updated successfully',
        data: {
          emailNotifications: user.emailNotificationsEnabled,
          pushNotifications: user.pushNotificationsEnabled,
        },
      });
    } catch (error) {
      console.error('Error updating notification preferences:', error);
      return res.status(500).json({
        success: false,
        message: 'Internal server error',
        error: error.message,
      });
    }
  }

  static async getNotificationPreferences(req, res) {
    try {
      const { id: userId } = req.user;

      if (!mongoose.Types.ObjectId.isValid(userId)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid user ID format',
        });
      }

      const user = await Account.findById(userId).select(
        'emailNotificationsEnabled pushNotificationsEnabled'
      );

      if (!user) {
        return res.status(404).json({
          success: false,
          message: 'User not found',
        });
      }

      return res.status(200).json({
        success: true,
        data: {
          emailNotifications: user.emailNotificationsEnabled || false,
          pushNotifications: user.pushNotificationsEnabled || false,
        },
      });
    } catch (error) {
      console.error('Error fetching notification preferences:', error);
      return res.status(500).json({
        success: false,
        message: 'Internal server error',
        error: error.message,
      });
    }
  }

  /**
   * Send a notification to a specific user (admin use)
   */
  static async sendNotification(req, res) {
    try {
      const { userId, title, message, type, data } = req.body;

      if (!mongoose.Types.ObjectId.isValid(userId)) {
        return res.status(400).json({
          success: false,
          message: 'Invalid user ID format',
        });
      }

      if (!title || !message || !type) {
        return res.status(400).json({
          success: false,
          message: 'Title, message, and type are required',
        });
      }

      const user = await Account.findById(userId);
      if (!user) {
        return res.status(404).json({
          success: false,
          message: 'User not found',
        });
      }

      const notification = await NotificationService.sendNotification(
        userId,
        title,
        message,
        type,
        data || {}
      );

      return res.status(201).json({
        success: true,
        message: 'Notification sent successfully',
        data: notification,
      });
    } catch (error) {
      console.error('Error sending notification:', error);
      return res.status(500).json({
        success: false,
        message: 'Internal server error',
        error: error.message,
      });
    }
  }

  /**
   * Send bulk notifications (admin use)
   */
  static async sendBulkNotifications(req, res) {
    try {
      const { userIds, title, message, type, data } = req.body;

      if (!userIds || !Array.isArray(userIds) || userIds.length === 0) {
        return res.status(400).json({
          success: false,
          message: 'User IDs array is required',
        });
      }

      if (!title || !message || !type) {
        return res.status(400).json({
          success: false,
          message: 'Title, message, and type are required',
        });
      }

      // Validate all user IDs
      const invalidIds = userIds.filter(id => !mongoose.Types.ObjectId.isValid(id));
      if (invalidIds.length > 0) {
        return res.status(400).json({
          success: false,
          message: 'Invalid user ID format detected',
          invalidIds,
        });
      }

      const results = await NotificationService.sendBulkNotifications(
        userIds,
        title,
        message,
        type,
        data || {}
      );

      return res.status(201).json({
        success: true,
        message: 'Bulk notifications sent successfully',
        data: {
          total: results.length,
          notifications: results,
        },
      });
    } catch (error) {
      console.error('Error sending bulk notifications:', error);
      return res.status(500).json({
        success: false,
        message: 'Internal server error',
        error: error.message,
      });
    }
  }

  /**
   * Get notification statistics (admin dashboard)
   */
  static async getNotificationStats(req, res) {
    try {
      const { days = 30 } = req.query;
      const startDate = new Date();
      startDate.setDate(startDate.getDate() - parseInt(days));

      const stats = await Notification.aggregate([
        {
          $match: {
            createdAt: { $gte: startDate }
          }
        },
        {
          $group: {
            _id: {
              date: { $dateToString: { format: '%Y-%m-%d', date: '$createdAt' } },
              type: '$type'
            },
            count: { $sum: 1 }
          }
        },
        {
          $group: {
            _id: '$_id.date',
            types: {
              $push: {
                type: '$_id.type',
                count: '$count'
              }
            },
            total: { $sum: '$count' }
          }
        },
        { $sort: { _id: 1 } }
      ]);

      // Get summary counts
      const summary = await Notification.aggregate([
        {
          $group: {
            _id: null,
            total: { $sum: 1 },
            unread: {
              $sum: { $cond: ['$isRead', 0, 1] }
            },
            read: {
              $sum: { $cond: ['$isRead', 1, 0] }
            }
          }
        }
      ]);

      return res.status(200).json({
        success: true,
        data: {
          daily: stats,
          summary: summary[0] || { total: 0, unread: 0, read: 0 }
        }
      });
    } catch (error) {
      console.error('Error fetching notification stats:', error);
      return res.status(500).json({
        success: false,
        message: 'Internal server error',
        error: error.message,
      });
    }
  }

  /**
   * Clean up old notifications (admin/cron job)
   */
  static async cleanupOldNotifications(req, res) {
    try {
      const { days = 90 } = req.query; // Default: delete notifications older than 90 days
      const cutoffDate = new Date();
      cutoffDate.setDate(cutoffDate.getDate() - parseInt(days));

      const result = await Notification.deleteMany({
        createdAt: { $lt: cutoffDate },
        isRead: true // Only delete read notifications
      });

      return res.status(200).json({
        success: true,
        message: 'Old notifications cleaned up successfully',
        data: {
          deletedCount: result.deletedCount,
          olderThan: `${days} days`
        }
      });
    } catch (error) {
      console.error('Error cleaning up notifications:', error);
      return res.status(500).json({
        success: false,
        message: 'Internal server error',
        error: error.message,
      });
    }
  }
}

module.exports = NotificationController;