const { uid } = require('./helpers');
const { appendToLog } = require('./logBackup');

// Which notification types each role can see
const ROLE_TYPES = {
  master_admin: ['product', 'order', 'client', 'stock_report', 'user', 'system', 'follow_up'],
  cashier: ['order', 'client', 'follow_up', 'system'],
  supplier: ['product', 'stock_report', 'system'],
};

async function createNotification(pool, { type, action, title, message, detail, entity, entityId, triggeredBy }, opts = {}) {
  const id = uid();
  try {
    // Insert notification
    await pool.query(
      'INSERT INTO notifications (id, type, action, title, message, detail, entity, entity_id, triggered_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)',
      [id, type, action, title, message || '', detail ? JSON.stringify(detail) : null, entity || null, entityId || null, triggeredBy || null]
    );

    // Get all active users and create read entries for those whose role matches
    const [users] = await pool.query("SELECT id, role FROM users WHERE status = 'active'");
    const values = [];
    for (const u of users) {
      const visibleTypes = ROLE_TYPES[u.role] || [];
      if (visibleTypes.includes(type)) {
        values.push([id, u.id]);
      }
    }

    if (values.length > 0) {
      const placeholders = values.map(() => '(?, ?)').join(',');
      const flat = values.flat();
      await pool.query(`INSERT INTO notification_reads (notification_id, user_id) VALUES ${placeholders}`, flat);
    }

    // Write to backup log (skip if flagged to avoid recursion)
    if (!opts.skipLogWrite) {
      const logEntry = { id, type, action, title, message, detail, entity, entityId, triggeredBy, timestamp: new Date().toISOString() };
      const rotated = appendToLog(logEntry);
      // If log rotated, notify master_admin
      if (rotated) {
        await createNotification(pool, {
          type: 'system', action: 'log_full',
          title: 'Log Backup Full',
          message: 'Activity log reached 1000 entries. A new archive has been created. Please download and clear old backups.',
          entity: 'system', entityId: 'log',
        }, { skipLogWrite: true });
      }
    }
  } catch (err) {
    console.error('Notification error:', err.message);
  }
  return id;
}

// Check low stock and create notifications (de-duplicated per 24h)
async function checkLowStock(pool, triggeredBy) {
  try {
    const [products] = await pool.query('SELECT id, name, stock_qty, low_threshold FROM products WHERE stock_qty <= low_threshold');
    for (const p of products) {
      // Check if already notified in last 24h
      const [existing] = await pool.query(
        "SELECT id FROM notifications WHERE type = 'system' AND action = 'low_stock' AND entity_id = ? AND created_at > DATE_SUB(NOW(), INTERVAL 24 HOUR)",
        [p.id]
      );
      if (existing.length === 0) {
        await createNotification(pool, {
          type: 'system', action: 'low_stock',
          title: 'Low Stock Alert',
          message: `${p.name} is at ${p.stock_qty} units (threshold: ${p.low_threshold})`,
          detail: { product: p },
          entity: 'product', entityId: p.id, triggeredBy,
        });
      }
    }
  } catch (err) {
    console.error('Low stock check error:', err.message);
  }
}

module.exports = { createNotification, checkLowStock, ROLE_TYPES };
