/**
 * NotificationService — fire-and-record notifications.
 *
 * 2026-07-21 scope:
 *   - Logs every notification to the `notifications` table
 *   - For 'in_app' type: marks the row as 'sent' (the teacher's
 *     inbox query reads the table; we don't actually push via WS)
 *   - For 'email' / 'sms' types: writes the row with status='pending'
 *     and logs to console — there is no email/SMS provider wired in
 *     the repo today. When one is added, the dispatch is the only
 *     piece that needs to change; the table is already there.
 *
 * Design:
 *   - Pure write side-effect; no retry, no queue. If a real provider
 *     is added later, switch 'pending' → 'sent' on success and
 *     'pending' → 'failed' with error_message on failure. Background
 *     workers can pick up 'pending' rows.
 *   - Errors are swallowed (logged) so a failed notification never
 *     blocks the calling user action (e.g. a reject still succeeds
 *     even if the email couldn't be queued).
 */

const { v4: uuidv4 } = require('uuid');

const send = (db, { recipientId, type, subject, body, relatedResource, metadata }) => {
  // Guard: only allow the three known types. The DB also has a CHECK
  // constraint but validating here gives a friendlier failure mode.
  const allowed = ['in_app', 'email', 'sms'];
  if (!allowed.includes(type)) {
    console.warn(`[notify] unknown type ${type}; defaulting to in_app`);
    type = 'in_app';
  }
  if (!recipientId) {
    console.warn('[notify] missing recipientId; skipping');
    return null;
  }
  // 'in_app' is "delivered" immediately (the table IS the inbox).
  // 'email' / 'sms' sit as 'pending' until a real provider is wired
  // in. The console.log is the placeholder for that provider call.
  const initialStatus = type === 'in_app' ? 'sent' : 'pending';
  try {
    const result = db.prepare(`
      INSERT INTO notifications
        (uid, recipient_id, type, subject, body, related_resource,
         status, sent_at, metadata, sync_status)
      VALUES (?, ?, ?, ?, ?, ?, ?, ${type === 'in_app' ? "CURRENT_TIMESTAMP" : "NULL"}, ?, 'pending')
    `).run(
      uuidv4(),
      recipientId,
      type,
      subject || null,
      body || null,
      relatedResource || null,
      initialStatus,
      metadata ? JSON.stringify(metadata) : null
    );
    const id = result.lastInsertRowid;
    setSyncPending(db, 'notifications', id);

    if (type === 'email' || type === 'sms') {
      // Placeholder: a real provider (e.g. Africa's Talking, Twilio,
      // SendGrid) would be invoked here. For now, the row stays at
      // status='pending' and an operator / follow-up PR can wire it.
      console.log(
        `[notify:stub] would ${type.toUpperCase()} → user ${recipientId}: ` +
        `"${subject || ''}" — body length ${(body || '').length}`
      );
    } else {
      console.log(
        `[notify:in_app] → user ${recipientId}: "${subject || ''}" (id=${id})`
      );
    }
    return id;
  } catch (e) {
    console.warn(`[notify] insert failed for recipient ${recipientId}:`, e.message);
    return null;
  }
};

const setSyncPending = (db, table, id) => {
  try {
    db.prepare(`UPDATE ${table} SET sync_status = 'pending' WHERE id = ?`).run(id);
  } catch (e) {
    // ignore — table may not be in this DB
  }
};

module.exports = { send };
