/**
 * models/contactMessage.js
 *
 * Admin → support contact messages. IDOR-safe by construction:
 *  - Primary key is a UUID v4 (non-guessable across users).
 *  - Every read is scoped to author_user_id (server-derived from session).
 *  - The route layer never trusts a client-supplied author_user_id.
 *  - getForUser() returns a row only if author matches; otherwise null.
 *
 * Schema (created in config/db.js):
 *   id (uuid), author_user_id, subject, body, priority, status,
 *   created_at, updated_at
 */

'use strict';

const crypto = require('crypto');
const { db } = require('../config/db');

const insertStmt = db.prepare(`
  INSERT INTO contact_messages
    (id, author_user_id, subject, body, priority, status, created_at, updated_at)
  VALUES (?, ?, ?, ?, ?, 'open', ?, ?)
`);

const getForUserStmt = db.prepare(`
  SELECT id, author_user_id, subject, body, priority, status, created_at, updated_at
    FROM contact_messages
   WHERE id = ? AND author_user_id = ?
`);

const listForUserStmt = db.prepare(`
  SELECT id, subject, priority, status, created_at, updated_at
    FROM contact_messages
   WHERE author_user_id = ?
   ORDER BY created_at DESC
   LIMIT ?
`);

const countForUserStmt = db.prepare(`
  SELECT COUNT(*) AS c FROM contact_messages WHERE author_user_id = ?
`);

function uuid() {
  // Node 14.17+ has crypto.randomUUID(). Fall back to a strong manual
  // v4 if for some reason the platform is older.
  if (typeof crypto.randomUUID === 'function') return crypto.randomUUID();
  const b = crypto.randomBytes(16);
  b[6] = (b[6] & 0x0f) | 0x40;
  b[8] = (b[8] & 0x3f) | 0x80;
  const h = b.toString('hex');
  return `${h.slice(0,8)}-${h.slice(8,12)}-${h.slice(12,16)}-${h.slice(16,20)}-${h.slice(20)}`;
}

function create({ authorUserId, subject, body, priority }) {
  const id = uuid();
  const now = Date.now();
  const pri = ['low', 'normal', 'high'].includes(priority) ? priority : 'normal';
  insertStmt.run(id, authorUserId, String(subject).slice(0, 200), String(body).slice(0, 4000), pri, now, now);
  return id;
}

// Returns the row only if it belongs to the requesting user. 404-equivalent
// for the caller (no leaked existence). The model never returns a row the
// user shouldn't see.
function getForUser({ id, authorUserId }) {
  return getForUserStmt.get(String(id), authorUserId) || null;
}

function listForUser({ authorUserId, limit = 50 }) {
  const n = Math.max(1, Math.min(200, parseInt(limit, 10) || 50));
  return listForUserStmt.all(authorUserId, n);
}

function countForUser({ authorUserId }) {
  return countForUserStmt.get(authorUserId).c;
}

module.exports = { create, getForUser, listForUser, countForUser, uuid };
