'use strict';
const db     = require('../../db/db');
const crypto = require('crypto');
const { emitToUser, invalidateSession } = require('../../ws-server');
const { emitToSession, hasAccess, canDraw } = require('./_shared');

function createSession(req, res) {
  const { class_id, user_ids, title = '' } = req.body;
  const teacher = req.user;

  const classroomEnabled = db.prepare("SELECT value FROM app_settings WHERE key='feature_classroom_enabled'").get();
  if (classroomEnabled?.value === '0') {
    return res.status(403).json({ error: 'Модуль онлайн-уроков отключён администратором' });
  }

  if (!class_id && (!user_ids || !user_ids.length)) {
    return res.status(400).json({ error: 'Укажите class_id или user_ids' });
  }

  if (class_id) {
    const cls = teacher.role === 'admin'
      ? db.prepare('SELECT id, name FROM classes WHERE id=?').get(class_id)
      : db.prepare('SELECT id, name FROM classes WHERE id=? AND teacher_id=?').get(class_id, teacher.id);
    if (!cls) return res.status(403).json({ error: 'Нет доступа к классу' });

    db.prepare(`UPDATE classroom_sessions SET status='ended', ended_at=datetime('now')
                WHERE class_id=? AND status='active'`).run(class_id);
  }

  const { lastInsertRowid } = db.prepare(
    `INSERT INTO classroom_sessions (class_id, teacher_id, title) VALUES (?,?,?)`
  ).run(class_id || null, teacher.id, title);

  const sessionId = Number(lastInsertRowid);
  db.prepare('INSERT INTO classroom_pages (session_id, page_num) VALUES (?,1)').run(sessionId);

  if (!class_id && user_ids) {
    const ins = db.prepare('INSERT OR IGNORE INTO classroom_invites (session_id, user_id) VALUES (?,?)');
    for (const uid of user_ids) ins.run(sessionId, uid);
  }

  const session = db.prepare('SELECT * FROM classroom_sessions WHERE id=?').get(sessionId);
  emitToSession(sessionId, { type: 'classroom_started', sessionId, title, classId: class_id || null, teacherName: teacher.name });
  res.json(session);
}

function getSession(req, res) {
  const sessionId = Number(req.params.id);
  const session = db.prepare('SELECT * FROM classroom_sessions WHERE id=?').get(sessionId);
  if (!session) return res.status(404).json({ error: 'Не найдено' });
  if (!hasAccess(session, req.user.id, req.user.role))
    return res.status(403).json({ error: 'Нет доступа' });

  const pageCount = db.prepare('SELECT COUNT(*) AS c FROM classroom_pages WHERE session_id=?').get(sessionId).c;
  const attendance = db.prepare(`
    SELECT a.user_id, u.name, a.joined_at, a.left_at
    FROM classroom_attendance a JOIN users u ON u.id = a.user_id
    WHERE a.session_id=? ORDER BY a.joined_at
  `).all(sessionId);
  const drawAllowed = canDraw(sessionId, req.user.id, session);
  res.json({ ...session, pageCount, attendance, canDraw: drawAllowed });
}

function endSession(req, res) {
  const sessionId = Number(req.params.id);
  const session = db.prepare('SELECT * FROM classroom_sessions WHERE id=?').get(sessionId);
  if (!session) return res.status(404).json({ error: 'Не найдено' });
  if (session.teacher_id !== req.user.id && req.user.role !== 'admin')
    return res.status(403).json({ error: 'Нет доступа' });

  db.prepare(`UPDATE classroom_sessions SET status='ended', ended_at=datetime('now') WHERE id=?`).run(sessionId);
  db.prepare(`UPDATE classroom_attendance SET left_at=datetime('now') WHERE session_id=? AND left_at IS NULL`).run(sessionId);
  db.prepare('DELETE FROM classroom_hands WHERE session_id=?').run(sessionId);
  db.prepare('DELETE FROM classroom_draw_permissions WHERE session_id=?').run(sessionId);
  db.prepare('DELETE FROM classroom_muted WHERE session_id=?').run(sessionId);
  emitToSession(sessionId, { type: 'classroom_ended', sessionId });
  res.json({ ok: true });
}

function getActiveSession(req, res) {
  const classId = Number(req.params.classId);
  if (req.user.role !== 'teacher' && req.user.role !== 'admin') {
    const isMember = db.prepare('SELECT 1 FROM class_members WHERE class_id=? AND user_id=?').get(classId, req.user.id);
    if (!isMember) return res.status(403).json({ error: 'Нет доступа' });
  }
  const session = db.prepare(
    `SELECT * FROM classroom_sessions WHERE class_id=? AND status='active' ORDER BY id DESC LIMIT 1`
  ).get(classId);
  if (!session) return res.json({ active: false });
  res.json({ active: true, session });
}

function getMyActive(req, res) {
  const userId = req.user.id;
  const sessions = db.prepare(`
    SELECT s.* FROM classroom_sessions s
    JOIN classroom_invites i ON i.session_id = s.id
    WHERE i.user_id=? AND s.status='active' ORDER BY s.id DESC
  `).all(userId);
  res.json({ sessions });
}

function joinSession(req, res) {
  const sessionId = Number(req.params.id);
  const session = db.prepare(`SELECT * FROM classroom_sessions WHERE id=? AND status='active'`).get(sessionId);
  if (!session) return res.status(404).json({ error: 'Сессия не активна' });
  if (!hasAccess(session, req.user.id, req.user.role))
    return res.status(403).json({ error: 'Нет доступа' });

  db.prepare(`
    INSERT INTO classroom_attendance (session_id, user_id)
    VALUES (?,?)
    ON CONFLICT(session_id, user_id) DO UPDATE SET joined_at=datetime('now'), left_at=NULL
  `).run(sessionId, req.user.id);

  invalidateSession(sessionId);
  emitToSession(sessionId, { type: 'classroom_user_joined', sessionId, userId: req.user.id, userName: req.user.name });

  const drawAllowed = canDraw(sessionId, req.user.id, session) && session.teacher_id !== req.user.id;
  if (drawAllowed) emitToUser(req.user.id, { type: 'classroom_draw_permitted', sessionId });

  const isMuted = !!db.prepare('SELECT 1 FROM classroom_muted WHERE session_id=? AND user_id=?').get(sessionId, req.user.id);
  if (isMuted) emitToUser(req.user.id, { type: 'classroom_muted', sessionId, by: null });

  res.json({ ok: true, canDraw: drawAllowed, muted: isMuted });
}

function leaveSession(req, res) {
  const sessionId = Number(req.params.id);
  db.prepare(`UPDATE classroom_attendance SET left_at=datetime('now')
              WHERE session_id=? AND user_id=? AND left_at IS NULL`).run(sessionId, req.user.id);

  invalidateSession(sessionId);
  const session = db.prepare('SELECT * FROM classroom_sessions WHERE id=?').get(sessionId);
  if (session) emitToSession(sessionId, { type: 'classroom_user_left', sessionId, userId: req.user.id });
  res.json({ ok: true });
}

function signal(req, res) {
  const sessionId = Number(req.params.id);
  const { target_user_id, payload } = req.body;
  if (!target_user_id || !payload) return res.status(400).json({ error: 'target_user_id и payload обязательны' });

  const session = db.prepare(`SELECT * FROM classroom_sessions WHERE id=? AND status='active'`).get(sessionId);
  if (!session) return res.status(404).json({ error: 'Сессия не активна' });
  if (!hasAccess(session, req.user.id, req.user.role)) return res.status(403).json({ error: 'Нет доступа' });
  if (!hasAccess(session, target_user_id, 'student')) return res.status(403).json({ error: 'Цель не является участником сессии' });

  emitToUser(target_user_id, { type: 'classroom_signal', sessionId, from: req.user.id, payload });
  res.json({ ok: true });
}

function getMySession(req, res) {
  const userId = req.user.id;
  const role   = req.user.role;
  let session  = null;

  if (role === 'teacher' || role === 'admin') {
    session = db.prepare(
      `SELECT * FROM classroom_sessions WHERE teacher_id=? AND status='active' ORDER BY id DESC LIMIT 1`
    ).get(userId);
  } else {
    session = db.prepare(`
      SELECT cs.* FROM classroom_sessions cs
      JOIN class_members cm ON cm.class_id = cs.class_id
      WHERE cm.user_id=? AND cs.status='active' ORDER BY cs.id DESC LIMIT 1
    `).get(userId);
    if (!session) {
      session = db.prepare(`
        SELECT cs.* FROM classroom_sessions cs
        JOIN classroom_invites ci ON ci.session_id = cs.id
        WHERE ci.user_id=? AND cs.status='active' ORDER BY cs.id DESC LIMIT 1
      `).get(userId);
    }
  }

  if (!session) return res.json({ session: null });

  const pageCount  = db.prepare('SELECT COUNT(*) AS c FROM classroom_pages WHERE session_id=?').get(session.id).c;
  const attendance = db.prepare(`
    SELECT a.user_id, u.name, a.joined_at, a.left_at
    FROM classroom_attendance a JOIN users u ON u.id = a.user_id
    WHERE a.session_id=? ORDER BY a.joined_at
  `).all(session.id);
  const wasJoined = attendance.some(a => a.user_id === userId);
  res.json({ session: { ...session, pageCount, attendance }, wasJoined });
}

function generateGuestToken(req, res) {
  const sessionId = Number(req.params.id);
  const session = db.prepare('SELECT id, teacher_id FROM classroom_sessions WHERE id=?').get(sessionId);
  if (!session) return res.status(404).json({ error: 'Not found' });
  if (session.teacher_id !== req.user.id && req.user.role !== 'admin')
    return res.status(403).json({ error: 'Forbidden' });
  const token = crypto.randomBytes(24).toString('base64url');
  db.prepare('UPDATE classroom_sessions SET guest_token=? WHERE id=?').run(token, sessionId);
  res.json({ token, url: `/guest-board.html?token=${token}` });
}

function revokeGuestToken(req, res) {
  const sessionId = Number(req.params.id);
  const session = db.prepare('SELECT id, teacher_id FROM classroom_sessions WHERE id=?').get(sessionId);
  if (!session) return res.status(404).json({ error: 'Not found' });
  if (session.teacher_id !== req.user.id && req.user.role !== 'admin')
    return res.status(403).json({ error: 'Forbidden' });
  db.prepare('UPDATE classroom_sessions SET guest_token=NULL WHERE id=?').run(sessionId);
  res.json({ ok: true });
}

function getGuestToken(req, res) {
  const sessionId = Number(req.params.id);
  const session = db.prepare('SELECT id, teacher_id, guest_token FROM classroom_sessions WHERE id=?').get(sessionId);
  if (!session) return res.status(404).json({ error: 'Not found' });
  if (session.teacher_id !== req.user.id && req.user.role !== 'admin')
    return res.status(403).json({ error: 'Forbidden' });
  if (!session.guest_token) return res.json({ token: null, url: null });
  res.json({ token: session.guest_token, url: `/guest-board.html?token=${session.guest_token}` });
}

module.exports = {
  createSession, getSession, endSession, getActiveSession, getMyActive,
  joinSession, leaveSession, signal, getMySession,
  generateGuestToken, revokeGuestToken, getGuestToken,
};
