const { all, one } = require('../db');

// Read-only access to the system-wide audit trail captured by db.audit(). Powers the admin
// Activity & Audit Trail viewer: filtered + paginated queries, filter facets, and CSV export.

const MAX_PAGE_SIZE = 200;

// Build a parameterized WHERE clause from the supported filters.
function buildWhere(filters = {}) {
  const clauses = [];
  const params = [];
  if (filters.actor) { clauses.push('al.actor_id = ?'); params.push(Number(filters.actor)); }
  if (filters.action) { clauses.push('al.action = ?'); params.push(filters.action); }
  if (filters.entity_type) { clauses.push('al.entity_type = ?'); params.push(filters.entity_type); }
  if (filters.from) { clauses.push('al.created_at >= ?'); params.push(String(filters.from)); }
  if (filters.to) { clauses.push('al.created_at <= ?'); params.push(`${String(filters.to)}`); }
  if (filters.q) {
    clauses.push('(al.entity_type LIKE ? OR al.entity_id LIKE ? OR al.action LIKE ? OR u.name LIKE ?)');
    const like = `%${filters.q}%`;
    params.push(like, like, like, like);
  }
  return { where: clauses.length ? `WHERE ${clauses.join(' AND ')}` : '', params };
}

const BASE = `
  FROM audit_logs al
  LEFT JOIN users u ON u.id = al.actor_id
`;

// Paginated query. Returns { rows, total, page, pageSize }.
function query(filters = {}, { page = 1, pageSize = 25 } = {}) {
  const size = Math.min(MAX_PAGE_SIZE, Math.max(1, Number(pageSize) || 25));
  const current = Math.max(1, Number(page) || 1);
  const { where, params } = buildWhere(filters);
  const total = one(`SELECT COUNT(*) AS c ${BASE} ${where}`, params).c;
  const rows = all(
    `SELECT al.id, al.actor_id, u.name AS actor_name, al.action, al.entity_type, al.entity_id,
            al.before_json, al.after_json, al.created_at
     ${BASE} ${where}
     ORDER BY al.id DESC
     LIMIT ? OFFSET ?`,
    [...params, size, (current - 1) * size]
  );
  return { rows, total, page: current, pageSize: size };
}

// All matching rows (no pagination) — used by CSV export. Capped to avoid unbounded memory.
function queryAll(filters = {}, limit = 50000) {
  const { where, params } = buildWhere(filters);
  return all(
    `SELECT al.id, al.actor_id, u.name AS actor_name, al.action, al.entity_type, al.entity_id,
            al.before_json, al.after_json, al.created_at
     ${BASE} ${where}
     ORDER BY al.id DESC
     LIMIT ?`,
    [...params, limit]
  );
}

// Distinct values for the filter dropdowns.
function facets() {
  return {
    actions: all('SELECT DISTINCT action FROM audit_logs ORDER BY action').map((r) => r.action),
    entity_types: all('SELECT DISTINCT entity_type FROM audit_logs ORDER BY entity_type').map((r) => r.entity_type),
    actors: all(
      `SELECT DISTINCT al.actor_id AS id, u.name AS name
       FROM audit_logs al LEFT JOIN users u ON u.id = al.actor_id
       WHERE al.actor_id IS NOT NULL
       ORDER BY u.name`
    )
  };
}

function csvCell(value) {
  const s = value === null || value === undefined ? '' : String(value);
  return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
}

// Serialize rows to CSV text.
function toCsv(rows) {
  const header = ['id', 'timestamp', 'actor', 'action', 'entity_type', 'entity_id', 'before', 'after'];
  const lines = [header.join(',')];
  for (const r of rows) {
    lines.push([
      r.id, r.created_at, r.actor_name || `#${r.actor_id || ''}`, r.action,
      r.entity_type, r.entity_id, r.before_json, r.after_json
    ].map(csvCell).join(','));
  }
  return lines.join('\n');
}

module.exports = { facets, query, queryAll, toCsv };
