'use strict';

// Install with:
//   const installV33MenuControlsRoutes = require('./v33-menu-controls-routes');
//   installV33MenuControlsRoutes(app, pool, authenticateToken);
//
// The frontend keeps an immediate same-browser copy. These routes make menu
// switches and active login time available to separate parent/student browsers.

function cleanControls(value) {
  const allowed = new Set([
    'dashboard', 'assignments', 'mygrades', 'courses', 'dailylogs',
    'attendance', 'reports', 'transcripts', 'calendar', 'messages', 'help'
  ]);
  const result = {};
  Object.entries(value && typeof value === 'object' ? value : {}).forEach(([key, enabled]) => {
    if (allowed.has(key)) result[key] = enabled === true;
  });
  if (Object.prototype.hasOwnProperty.call(result, 'reports')) result.transcripts = result.reports;
  if (Object.prototype.hasOwnProperty.call(result, 'transcripts')) result.reports = result.transcripts;
  return result;
}

async function canAccessStudent(req, pool, studentId) {
  const user = req.user || {};
  const role = String(user.role || user.type || user.user_type || '').toLowerCase();
  const userId = Number(user.id || user.user_id || user.parent_id || 0);
  const tokenStudentId = Number(user.student_id || user.student?.id || (role === 'student' ? user.id : 0));
  if (role.includes('admin')) return true;
  if (role === 'student') return tokenStudentId === studentId;
  if ((role === 'parent' || role === '') && userId > 0) {
    const candidates = ['parent_id', 'parent_user_id', 'user_id', 'account_id'];
    const columns = await pool.query(
      `SELECT column_name FROM information_schema.columns
       WHERE table_schema='public' AND table_name='students' AND column_name = ANY($1::text[])`,
      [candidates]
    );
    const ownerColumn = candidates.find(name => columns.rows.some(row => row.column_name === name));
    if (ownerColumn) {
      const owned = await pool.query(`SELECT 1 FROM students WHERE id=$1 AND ${ownerColumn}=$2 LIMIT 1`, [studentId, userId]);
      return owned.rowCount > 0;
    }
    const linkTable = await pool.query(`SELECT to_regclass('public.parent_student_links') AS name`);
    if (linkTable.rows[0]?.name) {
      const linked = await pool.query('SELECT 1 FROM parent_student_links WHERE parent_user_id=$1 AND student_id=$2 LIMIT 1', [userId, studentId]);
      return linked.rowCount > 0;
    }
    return false;
  }
  return false;
}

module.exports = function installV33MenuControlsRoutes(app, pool, authenticateToken) {
  if (!app || !pool) throw new Error('V33 menu-control routes require the Express app and PostgreSQL pool.');
  if (typeof authenticateToken !== 'function') throw new Error('V33 menu-control routes require the existing authentication middleware.');
  const protect = authenticateToken;

  app.get('/api/students/:studentId/menu-controls', protect, async (req, res) => {
    try {
      const studentId = Number(req.params.studentId);
      if (!Number.isInteger(studentId) || studentId <= 0) return res.status(400).json({ error: 'Invalid student ID' });
      if (!(await canAccessStudent(req, pool, studentId))) return res.status(403).json({ error: 'Student record access denied' });
      const result = await pool.query('SELECT controls, updated_at FROM student_menu_controls WHERE student_id = $1', [studentId]);
      return res.json({ student_id: studentId, controls: cleanControls(result.rows[0]?.controls || {}), updated_at: result.rows[0]?.updated_at || null });
    } catch (error) {
      console.error('V33 menu controls GET failed:', error);
      return res.status(500).json({ error: 'Unable to load student menu controls' });
    }
  });

  app.put('/api/students/:studentId/menu-controls', protect, async (req, res) => {
    try {
      const studentId = Number(req.params.studentId);
      if (!Number.isInteger(studentId) || studentId <= 0) return res.status(400).json({ error: 'Invalid student ID' });
      if (!(await canAccessStudent(req, pool, studentId))) return res.status(403).json({ error: 'Student record access denied' });
      const controls = cleanControls(req.body?.controls || req.body?.menu_controls || {});
      const result = await pool.query(
        `INSERT INTO student_menu_controls (student_id, controls, updated_at)
         VALUES ($1, $2::jsonb, NOW())
         ON CONFLICT (student_id) DO UPDATE
         SET controls = EXCLUDED.controls, updated_at = NOW()
         RETURNING controls, updated_at`,
        [studentId, JSON.stringify(controls)]
      );
      return res.json({ student_id: studentId, controls: cleanControls(result.rows[0].controls), updated_at: result.rows[0].updated_at });
    } catch (error) {
      console.error('V33 menu controls PUT failed:', error);
      return res.status(500).json({ error: 'Unable to save student menu controls' });
    }
  });

  app.post('/api/students/:studentId/activity-heartbeat', protect, async (req, res) => {
    try {
      const studentId = Number(req.params.studentId);
      if (!Number.isInteger(studentId) || studentId <= 0) return res.status(400).json({ error: 'Invalid student ID' });
      if (!(await canAccessStudent(req, pool, studentId))) return res.status(403).json({ error: 'Student record access denied' });
      const sessionKey = String(req.body?.session_id || req.body?.session_key || '').trim().slice(0, 160);
      if (!sessionKey) return res.status(400).json({ error: 'A session ID is required' });
      const rawStart = new Date(req.body?.started_at || Date.now());
      const now = new Date();
      const startedAt = Number.isNaN(rawStart.getTime()) || rawStart.getTime() > now.getTime() + 300000 ? now : rawStart;
      const ended = req.body?.ended === true;
      const result = await pool.query(
        `INSERT INTO student_activity_sessions
           (student_id, session_key, activity_type, started_at, last_activity_at, ended_at, subject, note, assignment_id, assignment_title, updated_at)
         VALUES ($1, $2, $3, $4, NOW(), CASE WHEN $5 THEN NOW() ELSE NULL END, $6, $7, $8, $9, NOW())
         ON CONFLICT (student_id, session_key) DO UPDATE
         SET last_activity_at = NOW(),
             ended_at = CASE WHEN $5 THEN NOW() ELSE student_activity_sessions.ended_at END,
             note = EXCLUDED.note,
             updated_at = NOW()
         RETURNING student_id, session_key, activity_type, started_at, last_activity_at, ended_at, subject, note, assignment_id, assignment_title`,
        [studentId, sessionKey, 'login', startedAt.toISOString(), ended, 'General Learning', String(req.body?.note || 'Student login session').slice(0, 300), null, null]
      );
      return res.json({ session: result.rows[0] });
    } catch (error) {
      console.error('V33 activity heartbeat failed:', error);
      return res.status(500).json({ error: 'Unable to update student activity time' });
    }
  });

  app.get('/api/students/:studentId/activity-sessions', protect, async (req, res) => {
    try {
      const studentId = Number(req.params.studentId);
      if (!Number.isInteger(studentId) || studentId <= 0) return res.status(400).json({ error: 'Invalid student ID' });
      if (!(await canAccessStudent(req, pool, studentId))) return res.status(403).json({ error: 'Student record access denied' });
      const result = await pool.query(
        `SELECT student_id, session_key, activity_type, started_at, last_activity_at, ended_at,
                subject, note, assignment_id, assignment_title,
                GREATEST(0, EXTRACT(EPOCH FROM (COALESCE(ended_at, last_activity_at) - started_at)))::INTEGER AS seconds
         FROM student_activity_sessions
         WHERE student_id = $1 AND started_at >= NOW() - INTERVAL '400 days'
         ORDER BY started_at DESC`,
        [studentId]
      );
      return res.json({ sessions: result.rows });
    } catch (error) {
      console.error('V33 activity sessions GET failed:', error);
      return res.status(500).json({ error: 'Unable to load student activity sessions' });
    }
  });
};
