const database = require('../config/database');
const { v4: uuidv4 } = require('uuid');

// Global variable to store io instance
let io = null;

// Function to set the io instance
const setSocketIO = (socketIO) => {
  io = socketIO;
};

class AdminNotification {
  constructor(data = {}) {
    this.id = data.id;
    this.type = data.type;
    this.message = data.message;
    this.reference_id = data.reference_id;
    this.reference_type = data.reference_type;
    this.is_read = data.is_read || false;
    this.created_at = data.created_at;
    this.read_at = data.read_at;
  }

  static async create(data) {
    const id = uuidv4();
    const query = `
      INSERT INTO admin_notifications (
        id, type, message, reference_id, reference_type, is_read
      ) VALUES ($1, $2, $3, $4, $5, $6)
      RETURNING *
    `;
    const values = [
      id,
      data.type,
      data.message,
      data.reference_id || null,
      data.reference_type || null,
      data.is_read || false
    ];
    const result = await database.query(query, values);
    const notification = new AdminNotification(result.rows[0]);
    
    // Emit real-time notification via WebSocket
    if (io) {
      io.to('admin-notifications').emit('new-notification', notification);
      
      // Also emit updated count
      const counts = await AdminNotification.getCounts();
      io.to('admin-notifications').emit('notification-count', counts);
    }
    
    return notification;
  }

  static async getUnread(limit = 50) {
    const query = `
      SELECT * FROM admin_notifications
      WHERE is_read = false
      ORDER BY created_at DESC
      LIMIT $1
    `;
    const result = await database.query(query, [limit]);
    return result.rows.map(r => new AdminNotification(r));
  }

  static async getAll(limit = 100, offset = 0) {
    const query = `
      SELECT * FROM admin_notifications
      ORDER BY created_at DESC
      LIMIT $1 OFFSET $2
    `;
    const result = await database.query(query, [limit, offset]);
    return result.rows.map(r => new AdminNotification(r));
  }

  static async markAsRead(id) {
    const query = `
      UPDATE admin_notifications
      SET is_read = true, read_at = NOW()
      WHERE id = $1
      RETURNING *
    `;
    const result = await database.query(query, [id]);
    const notification = result.rows.length ? new AdminNotification(result.rows[0]) : null;
    
    // Emit updated count via WebSocket
    if (io && notification) {
      const counts = await AdminNotification.getCounts();
      io.to('admin-notifications').emit('notification-count', counts);
      io.to('admin-notifications').emit('notification-read', { id });
    }
    
    return notification;
  }

  static async markAllAsRead() {
    const query = `
      UPDATE admin_notifications
      SET is_read = true, read_at = NOW()
      WHERE is_read = false
    `;
    const result = await database.query(query);
    
    // Emit updated count via WebSocket
    if (io && result.rowCount > 0) {
      const counts = await AdminNotification.getCounts();
      io.to('admin-notifications').emit('notification-count', counts);
      io.to('admin-notifications').emit('all-notifications-read');
    }
    
    return result.rowCount;
  }

  static async getCounts() {
    const query = `
      SELECT 
        COUNT(*) as total,
        COUNT(CASE WHEN is_read = false THEN 1 END) as unread,
        COUNT(CASE WHEN is_read = true THEN 1 END) as read
      FROM admin_notifications
    `;
    const result = await database.query(query);
    return result.rows[0];
  }

  static async deleteOld(daysOld = 30) {
    const query = `
      DELETE FROM admin_notifications
      WHERE created_at < NOW() - INTERVAL '${daysOld} days'
    `;
    const result = await database.query(query);
    return result.rowCount;
  }

  // Convenience methods for creating specific notification types
  static async notifyNewFeature(featureId, featureName) {
    return await AdminNotification.create({
      type: 'new_feature',
      message: `New custom feature submitted: "${featureName}"`,
      reference_id: featureId,
      reference_type: 'custom_feature'
    });
  }

  static async notifyFeatureReviewed(featureId, featureName, status) {
    return await AdminNotification.create({
      type: 'feature_reviewed',
      message: `Feature "${featureName}" has been ${status}`,
      reference_id: featureId,
      reference_type: 'custom_feature'
    });
  }

  static async notifyNewTemplate(templateId, templateName) {
    return await AdminNotification.create({
      type: 'new_template',
      message: `New custom template submitted: "${templateName}"`,
      reference_id: templateId,
      reference_type: 'custom_template'
    });
  }

  static async notifyTemplateReviewed(templateId, templateName, status) {
    return await AdminNotification.create({
      type: 'template_reviewed',
      message: `Template "${templateName}" has been ${status}`,
      reference_id: templateId,
      reference_type: 'custom_template'
    });
  }
}

// Export the setSocketIO function along with the class
AdminNotification.setSocketIO = setSocketIO;

module.exports = AdminNotification;
