'use strict';
/* contentAccess — резолвинг доступа к учебникам / экзамен-модулям.
 *
 * Модель: ALLOWLIST. По умолчанию закрыто. Правило ученика важнее правила
 * класса. См. миграцию 040_content_access.sql.
 *
 *   canAccessTextbook(user, slug)  → bool
 *   canAccessExam(user, examKey)   → bool
 *   filterTextbooks(user, rows)    → отфильтрованный список (rows[*].slug)
 *   allowedRefs(userId, type)      → Set<content_ref> доступных пользователю
 */
const db = require('../db/db');

const PRIVILEGED = new Set(['admin', 'teacher']);

const _parentOf = db.prepare('SELECT parent_slug FROM textbooks WHERE slug = ?');
/* Глава наследует доступ родителя-хаба; верхнеуровневый учебник — ключ = own slug. */
function textbookAccessKey(slug) {
  const row = _parentOf.get(slug);
  return row && row.parent_slug ? row.parent_slug : slug;
}

const _studentRule = db.prepare(`
  SELECT allow FROM content_access
   WHERE content_type = ? AND content_ref = ? AND scope = 'student' AND target_id = ?
`);
const _classRule = db.prepare(`
  SELECT MAX(allow) AS any_allow, COUNT(*) AS n
    FROM content_access
   WHERE content_type = ? AND content_ref = ? AND scope = 'class'
     AND target_id IN (SELECT class_id FROM class_members WHERE user_id = ?)
`);

function resolve(userId, type, ref) {
  const s = _studentRule.get(type, ref, userId);
  if (s) return s.allow === 1;                 // правило ученика побеждает
  const c = _classRule.get(type, ref, userId);
  if (c && c.n > 0) return c.any_allow === 1;  // открыт хотя бы одним классом
  return false;                                // allowlist — по умолчанию закрыто
}

function canAccess(user, type, ref) {
  if (!user) return false;
  if (PRIVILEGED.has(user.role)) return true;  // админ/учитель видят весь контент
  return resolve(user.id, type, ref);
}

function canAccessTextbook(user, slug) {
  return canAccess(user, 'textbook', textbookAccessKey(slug));
}
function canAccessExam(user, examKey) {
  return canAccess(user, 'exam', examKey);
}

/* Множество доступных пользователю content_ref для типа (bulk, для каталога). */
const _allStudentRules = db.prepare(`
  SELECT content_ref, allow FROM content_access
   WHERE content_type = ? AND scope = 'student' AND target_id = ?
`);
const _allClassRules = db.prepare(`
  SELECT content_ref, MAX(allow) AS any_allow
    FROM content_access
   WHERE content_type = ? AND scope = 'class'
     AND target_id IN (SELECT class_id FROM class_members WHERE user_id = ?)
   GROUP BY content_ref
`);
function allowedRefs(userId, type) {
  const out = new Set();
  for (const r of _allClassRules.all(type, userId)) {
    if (r.any_allow === 1) out.add(r.content_ref);
  }
  for (const r of _allStudentRules.all(type, userId)) {
    if (r.allow === 1) out.add(r.content_ref);   // ученик-разрешение добавляет
    else out.delete(r.content_ref);              // ученик-запрет снимает
  }
  return out;
}

/* Фильтрует список учебников верхнего уровня (каждый row имеет .slug). */
function filterTextbooks(user, rows) {
  if (!user) return [];
  if (PRIVILEGED.has(user.role)) return rows;
  const allow = allowedRefs(user.id, 'textbook');
  return rows.filter(r => allow.has(r.slug));
}

module.exports = {
  PRIVILEGED,
  textbookAccessKey,
  canAccess,
  canAccessTextbook,
  canAccessExam,
  allowedRefs,
  filterTextbooks,
};
