/**
 * Public (no-auth) guest classroom routes.
 * Guests access the whiteboard read-only via a token in the URL.
 *
 *  GET  /api/classroom/guest/:token           — session info (pre-join)
 *  POST /api/classroom/guest/:token/join      — choose display name, get guestId
 *  GET  /api/classroom/guest/:token/strokes   — strokes for ?page_num=N
 *  GET  /api/classroom/guest/:token/stream    — SSE stream (?guestId=X)
 *  POST /api/classroom/guest/:token/leave     — notify departure (optional)
 */

const router  = require('express').Router();
const crypto  = require('crypto');
const db      = require('../db/db');
const { addGuestClient, removeGuestClient, emitToGuests, emit } = require('../sse');

/* ── In-memory guest registry (cleared on server restart — fine for guests) */
const guests = new Map(); // guestId → { name, sessionId, connectedAt }

/* Helper: look up session by token (active only) */
function sessionByToken(token) {
  return db.prepare(
    "SELECT id, title, status, current_page, teacher_id FROM classroom_sessions WHERE guest_token=?"
  ).get(token);
}

/* Helper: emit guest-joined/left to the real participants of the session */
function notifySession(sessionId, data) {
  const session = db.prepare('SELECT class_id, teacher_id FROM classroom_sessions WHERE id=?').get(sessionId);
  if (!session) return;
  const { emit: _emit, emitToClass } = require('../sse');
  if (session.class_id) {
    emitToClass(session.class_id, data);
    _emit(session.teacher_id, data);
  } else {
    _emit(session.teacher_id, data);
    const invites = db.prepare('SELECT user_id FROM classroom_invites WHERE session_id=?').all(sessionId);
    for (const { user_id } of invites) _emit(user_id, data);
  }
}

/* ── GET /api/classroom/guest/:token ─── session info (pre-join screen) */
router.get('/:token', (req, res) => {
  const session = sessionByToken(req.params.token);
  if (!session) return res.status(404).json({ error: 'Ссылка недействительна' });

  const pageCount = db.prepare(
    'SELECT COUNT(*) AS c FROM classroom_pages WHERE session_id=?'
  ).get(session.id).c || 1;

  res.json({
    id:           session.id,
    title:        session.title || 'Онлайн-урок',
    status:       session.status,
    current_page: session.current_page || 1,
    page_count:   pageCount,
  });
});

/* ── POST /api/classroom/guest/:token/join ─── choose name, get guestId */
router.post('/:token/join', (req, res) => {
  const session = sessionByToken(req.params.token);
  if (!session) return res.status(404).json({ error: 'Ссылка недействительна' });
  if (session.status !== 'active')
    return res.status(403).json({ error: 'Урок ещё не начался или уже завершён' });

  const rawName = (req.body?.name || '').trim().slice(0, 40).replace(/[<>"&]/g, '');
  const name    = rawName || 'Гость';

  const guestId = 'g_' + crypto.randomBytes(12).toString('base64url');
  guests.set(guestId, { name, sessionId: session.id, connectedAt: Date.now() });

  // Notify real participants that a guest joined
  notifySession(session.id, {
    type:       'classroom_guest_joined',
    sessionId:  session.id,
    guestId,
    guestName:  name,
  });

  const pageCount = db.prepare(
    'SELECT COUNT(*) AS c FROM classroom_pages WHERE session_id=?'
  ).get(session.id).c || 1;

  res.json({
    guestId,
    sessionId:    session.id,
    title:        session.title || 'Онлайн-урок',
    current_page: session.current_page || 1,
    page_count:   pageCount,
  });
});

/* ── GET /api/classroom/guest/:token/strokes ─── whiteboard strokes */
router.get('/:token/strokes', (req, res) => {
  const session = sessionByToken(req.params.token);
  if (!session) return res.status(404).json({ error: 'Ссылка недействительна' });
  if (session.status !== 'active')
    return res.status(403).json({ error: 'Урок не активен' });

  const pageNum  = Math.max(1, Number(req.query.page_num) || 1);
  const sinceSeq = Number(req.query.since_seq) || 0;

  const strokes = sinceSeq > 0
    ? db.prepare(
        'SELECT id, tool, data, seq FROM classroom_strokes WHERE session_id=? AND page_num=? AND seq > ? ORDER BY seq'
      ).all(session.id, pageNum, sinceSeq)
    : db.prepare(
        'SELECT id, tool, data, seq FROM classroom_strokes WHERE session_id=? AND page_num=? ORDER BY seq'
      ).all(session.id, pageNum);

  const pageRow = db.prepare(
    'SELECT template, name FROM classroom_pages WHERE session_id=? AND page_num=?'
  ).get(session.id, pageNum);

  const parsed = strokes.map(s => ({ ...s, data: JSON.parse(s.data || '{}') }));
  res.json({ strokes: parsed, template: pageRow?.template || 'blank', seq: parsed.at(-1)?.seq || 0 });
});

/* ── GET /api/classroom/guest/:token/stream ─── SSE */
router.get('/:token/stream', (req, res) => {
  const session = sessionByToken(req.params.token);
  if (!session) return res.status(404).end();
  if (session.status !== 'active') return res.status(403).end();

  const guestId = req.query.guestId;
  const guest   = guestId ? guests.get(guestId) : null;

  res.setHeader('Content-Type',  'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection',    'keep-alive');
  res.setHeader('X-Accel-Buffering', 'no'); // nginx: disable buffering
  res.flushHeaders();
  res.write(`data: ${JSON.stringify({ type: 'connected' })}\n\n`);

  addGuestClient(session.id, res);

  req.on('close', () => {
    removeGuestClient(session.id, res);
    if (guest) {
      guests.delete(guestId);
      notifySession(session.id, {
        type:      'classroom_guest_left',
        sessionId: session.id,
        guestId,
        guestName: guest.name,
      });
    }
  });
});

/* ── POST /api/classroom/guest/:token/leave ─── explicit goodbye */
router.post('/:token/leave', (req, res) => {
  const guestId = req.body?.guestId;
  const guest   = guestId ? guests.get(guestId) : null;
  if (guest) {
    guests.delete(guestId);
    notifySession(guest.sessionId, {
      type:      'classroom_guest_left',
      sessionId: guest.sessionId,
      guestId,
      guestName: guest.name,
    });
  }
  res.json({ ok: true });
});

module.exports = router;
