'use strict';
const router = require('express').Router();
const db = require('../db/db');
const { authMiddleware, requireRole } = require('../middleware/auth');
const { emit } = require('../sse');

router.use(authMiddleware);

/* Parse "1-5", "1,3,7", "1-3,5,7-9" → [1,2,3,...]; empty → [1..fallback] */
function parseTextbookParas(spec, fallback) {
  if (!spec || !spec.trim()) return Array.from({ length: fallback || 0 }, (_, i) => i + 1);
  const out = new Set();
  for (const chunk of spec.split(',')) {
    const part = chunk.trim();
    if (!part) continue;
    const dash = part.match(/^(\d+)\s*[-–]\s*(\d+)$/);
    if (dash) {
      const a = Number(dash[1]), b = Number(dash[2]);
      for (let i = Math.min(a, b); i <= Math.max(a, b); i++) out.add(i);
    } else if (/^\d+$/.test(part)) out.add(Number(part));
  }
  return [...out].sort((a, b) => a - b);
}

/* After a paragraph is marked read, scan user's textbook assignments and mark
   completed if all required paragraphs are now in their read set. */
function checkAssignmentCompletion(userId, textbookId, readSet) {
  const candidates = db.prepare(`
    SELECT a.id, a.title, a.created_by, a.textbook_paragraphs, t.para_count
    FROM assignments a
    JOIN textbooks t ON t.id = a.textbook_id
    LEFT JOIN assignment_completion ac ON ac.assignment_id = a.id AND ac.user_id = ?
    WHERE a.textbook_id = ?
      AND ac.assignment_id IS NULL
      AND (
        a.user_id = ?
        OR (a.user_id IS NULL AND a.class_id IS NOT NULL
            AND EXISTS (SELECT 1 FROM class_members cm WHERE cm.class_id = a.class_id AND cm.user_id = ?))
      )
  `).all(userId, textbookId, userId, userId);

  for (const a of candidates) {
    const required = parseTextbookParas(a.textbook_paragraphs, a.para_count);
    if (!required.length) continue;
    const allRead = required.every(n => readSet.has('p' + n));
    if (allRead) {
      db.prepare('INSERT OR IGNORE INTO assignment_completion (assignment_id, user_id) VALUES (?, ?)').run(a.id, userId);
      try {
        emit(a.created_by, {
          type: 'notification', notif_type: 'assignment_done',
          message: `Ученик завершил чтение: «${a.title}»`, link: '/classes',
        });
      } catch {}
    }
  }
}

/* ════════════════════════════════════════════════
   LITERAL ROUTES FIRST — must come before /:slug
   ════════════════════════════════════════════════ */

/* GET /api/textbooks — catalog list (top-level only) with current user's progress.
   Rows with a parent_slug are chapters hidden from the catalog but still directly accessible. */
router.get('/', (req, res) => {
  const rows = db.prepare(`
    SELECT t.id, t.slug, t.subject, t.grade, t.title, t.author, t.description,
           t.html_path, t.para_count, t.color, t.sort_order
    FROM textbooks t WHERE t.is_active = 1 AND t.parent_slug IS NULL
    ORDER BY t.sort_order, t.subject, t.grade
  `).all();

  const myProgress = db.prepare(`
    SELECT textbook_id, paragraphs_read, last_para, last_at FROM textbook_progress WHERE user_id=?
  `).all(req.user.id);
  const progressById = {};
  for (const p of myProgress) {
    let arr = [];
    try { arr = JSON.parse(p.paragraphs_read || '[]'); } catch {}
    progressById[p.textbook_id] = { read: arr, last_para: p.last_para, last_at: p.last_at };
  }

  /* Prepared statements reused for each hub row that has children. */
  const stmtChildren = db.prepare(`
    SELECT id FROM textbooks WHERE parent_slug = ? AND is_active = 1
  `);
  const stmtChildProgress = db.prepare(`
    SELECT textbook_id, paragraphs_read, last_para, last_at FROM textbook_progress
    WHERE user_id = ? AND textbook_id IN (SELECT id FROM textbooks WHERE parent_slug = ?)
    ORDER BY last_at DESC
  `);

  const textbooks = rows.map(t => {
    const children = stmtChildren.all(t.slug);
    if (children.length === 0) {
      return { ...t, progress: progressById[t.id] || { read: [], last_para: null, last_at: null } };
    }

    /* Hub: aggregate progress across all child chapters. */
    const childRows = stmtChildProgress.all(req.user.id, t.slug);
    const readSet = new Set();
    let last_para = null;
    let last_at   = null;

    for (const cp of childRows) {
      let arr = [];
      try { arr = JSON.parse(cp.paragraphs_read || '[]'); } catch {}
      for (const item of arr) readSet.add(item);
      /* childRows ordered by last_at DESC — first row is the most recent. */
      if (last_para === null) {
        last_para = cp.last_para;
        last_at   = cp.last_at;
      }
    }

    return {
      ...t,
      progress: { read: [...readSet], last_para, last_at },
    };
  });

  res.json({ textbooks });
});

/* GET /api/textbooks/bookmarks/all — all my bookmarks across textbooks */
router.get('/bookmarks/all', (req, res) => {
  const rows = db.prepare(`
    SELECT b.id, b.para, b.text, b.note, b.color, b.created_at,
           t.slug AS textbook_slug, t.title AS textbook_title, t.color AS textbook_color
    FROM textbook_bookmarks b
    JOIN textbooks t ON t.id = b.textbook_id
    WHERE b.user_id=? ORDER BY b.id DESC
  `).all(req.user.id);
  res.json({ bookmarks: rows });
});

/* PATCH /api/textbooks/bookmarks/:id — update note/color */
router.patch('/bookmarks/:id', (req, res) => {
  const id = Number(req.params.id);
  const b = db.prepare('SELECT id, user_id FROM textbook_bookmarks WHERE id=?').get(id);
  if (!b) return res.status(404).json({ error: 'Закладка не найдена' });
  if (b.user_id !== req.user.id) return res.status(403).json({ error: 'Нет доступа' });

  const updates = [], params = [];
  if (typeof req.body?.note === 'string') { updates.push('note=?'); params.push(req.body.note.slice(0, 1000)); }
  if (req.body?.color && ['yellow','green','blue','pink'].includes(req.body.color)) {
    updates.push('color=?'); params.push(req.body.color);
  }
  if (!updates.length) return res.json({ ok: true });
  params.push(id);
  db.prepare(`UPDATE textbook_bookmarks SET ${updates.join(', ')} WHERE id=?`).run(...params);
  res.json({ ok: true });
});

/* DELETE /api/textbooks/bookmarks/:id */
router.delete('/bookmarks/:id', (req, res) => {
  const id = Number(req.params.id);
  const b = db.prepare('SELECT id, user_id FROM textbook_bookmarks WHERE id=?').get(id);
  if (!b) return res.status(404).json({ error: 'Закладка не найдена' });
  if (b.user_id !== req.user.id) return res.status(403).json({ error: 'Нет доступа' });
  db.prepare('DELETE FROM textbook_bookmarks WHERE id=?').run(id);
  res.json({ ok: true });
});

/* ════════════════════════════════════════════════
   :slug ROUTES (catch-all per textbook)
   ════════════════════════════════════════════════ */

/* GET /api/textbooks/:slug/children — chapter list for a hub textbook, with per-user progress.
   Used by hub pages to render chapter cards and progress bars. */
// @public-by-design: router-level authMiddleware (line 7) covers all routes in this file
router.get('/:slug/children', (req, res) => {
  const hub = db.prepare('SELECT id FROM textbooks WHERE slug=? AND is_active=1').get(req.params.slug);
  if (!hub) return res.status(404).json({ error: 'Учебник не найден' });

  const children = db.prepare(`
    SELECT t.id, t.slug, t.title, t.description, t.html_path, t.para_count, t.sort_order, t.color
    FROM textbooks t
    WHERE t.parent_slug = ? AND t.is_active = 1
    ORDER BY t.sort_order
  `).all(req.params.slug);

  const progressRows = db.prepare(`
    SELECT textbook_id, paragraphs_read, last_para, last_at
    FROM textbook_progress
    WHERE user_id = ? AND textbook_id IN (
      SELECT id FROM textbooks WHERE parent_slug = ? AND is_active = 1
    )
  `).all(req.user.id, req.params.slug);

  const progMap = {};
  for (const p of progressRows) {
    let arr = [];
    try { arr = JSON.parse(p.paragraphs_read || '[]'); } catch {}
    progMap[p.textbook_id] = { read: arr, last_para: p.last_para, last_at: p.last_at };
  }

  res.json({
    children: children.map(c => ({
      ...c,
      progress: progMap[c.id] || { read: [], last_para: null, last_at: null },
    })),
  });
});

/* GET /api/textbooks/:slug — single textbook detail */
router.get('/:slug', (req, res) => {
  const t = db.prepare('SELECT * FROM textbooks WHERE slug=? AND is_active=1').get(req.params.slug);
  if (!t) return res.status(404).json({ error: 'Учебник не найден' });
  const p = db.prepare('SELECT paragraphs_read, last_para, last_at FROM textbook_progress WHERE user_id=? AND textbook_id=?').get(req.user.id, t.id);
  let read = [];
  if (p) { try { read = JSON.parse(p.paragraphs_read || '[]'); } catch {} }
  res.json({ ...t, progress: { read, last_para: p?.last_para || null, last_at: p?.last_at || null } });
});

/* POST /api/textbooks/:slug/progress — update progress */
router.post('/:slug/progress', (req, res) => {
  const t = db.prepare('SELECT id FROM textbooks WHERE slug=? AND is_active=1').get(req.params.slug);
  if (!t) return res.status(404).json({ error: 'Учебник не найден' });

  const { last_para, mark_read, mark_unread } = req.body || {};
  const existing = db.prepare('SELECT paragraphs_read FROM textbook_progress WHERE user_id=? AND textbook_id=?').get(req.user.id, t.id);
  let arr = [];
  if (existing) { try { arr = JSON.parse(existing.paragraphs_read || '[]'); } catch {} }
  if (mark_read && typeof mark_read === 'string' && !arr.includes(mark_read)) arr.push(mark_read);
  if (mark_unread && typeof mark_unread === 'string') arr = arr.filter(p => p !== mark_unread);

  db.prepare(`
    INSERT INTO textbook_progress (user_id, textbook_id, paragraphs_read, last_para, last_at)
    VALUES (?, ?, ?, ?, datetime('now'))
    ON CONFLICT(user_id, textbook_id) DO UPDATE SET
      paragraphs_read = excluded.paragraphs_read,
      last_para       = COALESCE(excluded.last_para, textbook_progress.last_para),
      last_at         = excluded.last_at
  `).run(req.user.id, t.id, JSON.stringify(arr), last_para || null);

  if (mark_read) {
    try { checkAssignmentCompletion(req.user.id, t.id, new Set(arr)); } catch {}
  }
  res.json({ ok: true, read: arr });
});

/* GET /api/textbooks/:slug/bookmarks — list my bookmarks for this textbook */
router.get('/:slug/bookmarks', (req, res) => {
  const t = db.prepare('SELECT id FROM textbooks WHERE slug=?').get(req.params.slug);
  if (!t) return res.status(404).json({ error: 'Учебник не найден' });
  const rows = db.prepare(`
    SELECT id, para, text, note, color, created_at FROM textbook_bookmarks
    WHERE user_id=? AND textbook_id=? ORDER BY id DESC
  `).all(req.user.id, t.id);
  res.json({ bookmarks: rows });
});

/* POST /api/textbooks/:slug/bookmarks — create */
router.post('/:slug/bookmarks', (req, res) => {
  const t = db.prepare('SELECT id FROM textbooks WHERE slug=?').get(req.params.slug);
  if (!t) return res.status(404).json({ error: 'Учебник не найден' });
  const { para, text, note = '', color = 'yellow' } = req.body || {};
  if (!text || typeof text !== 'string') return res.status(400).json({ error: 'text required' });
  const VALID = new Set(['yellow', 'green', 'blue', 'pink']);
  const safeColor = VALID.has(color) ? color : 'yellow';
  const r = db.prepare(`
    INSERT INTO textbook_bookmarks (user_id, textbook_id, para, text, note, color)
    VALUES (?, ?, ?, ?, ?, ?)
  `).run(req.user.id, t.id, para || null, text.slice(0, 400), String(note).slice(0, 1000), safeColor);
  res.status(201).json({ id: r.lastInsertRowid });
});

/* GET /api/textbooks/:slug/class-progress — teacher view (per-student progress) */
router.get('/:slug/class-progress', requireRole('teacher', 'admin'), (req, res) => {
  const t = db.prepare('SELECT id, para_count FROM textbooks WHERE slug=?').get(req.params.slug);
  if (!t) return res.status(404).json({ error: 'Учебник не найден' });
  const classId = Number(req.query.class_id);
  if (!classId) return res.status(400).json({ error: 'class_id обязателен' });
  if (req.user.role === 'teacher') {
    const own = db.prepare('SELECT 1 FROM classes WHERE id=? AND teacher_id=?').get(classId, req.user.id);
    if (!own) return res.status(403).json({ error: 'Нет доступа к классу' });
  }
  const rows = db.prepare(`
    SELECT u.id AS user_id, u.name,
           COALESCE(tp.paragraphs_read, '[]') AS paragraphs_read,
           tp.last_para, tp.last_at
    FROM class_members cm
    JOIN users u ON u.id = cm.user_id
    LEFT JOIN textbook_progress tp ON tp.user_id = u.id AND tp.textbook_id = ?
    WHERE cm.class_id = ?
    ORDER BY u.name
  `).all(t.id, classId);
  res.json({
    total_paragraphs: t.para_count,
    students: rows.map(r => {
      let read = [];
      try { read = JSON.parse(r.paragraphs_read); } catch {}
      return {
        user_id: r.user_id, name: r.name,
        read_count: read.length, paragraphs_read: read,
        last_para: r.last_para, last_at: r.last_at,
      };
    }),
  });
});

/* ════════════════════════════════════════════════
   ADMIN endpoints — full catalog management
   ════════════════════════════════════════════════ */

/* GET /api/textbooks/admin/all — list ALL textbooks including inactive */
router.get('/admin/all', requireRole('admin'), (_req, res) => {
  const rows = db.prepare(`
    SELECT t.id, t.slug, t.subject, t.grade, t.title, t.author, t.description,
           t.html_path, t.para_count, t.color, t.sort_order, t.is_active, t.created_at,
           (SELECT COUNT(*) FROM textbook_progress WHERE textbook_id = t.id) AS readers
    FROM textbooks t ORDER BY t.sort_order, t.subject, t.grade
  `).all();
  res.json({ textbooks: rows });
});

/* PATCH /api/textbooks/admin/:id — edit textbook (admin only) */
router.patch('/admin/:id', requireRole('admin'), (req, res) => {
  const id = Number(req.params.id);
  const t = db.prepare('SELECT id FROM textbooks WHERE id=?').get(id);
  if (!t) return res.status(404).json({ error: 'Учебник не найден' });

  const allowed = ['title', 'author', 'description', 'subject', 'grade', 'color', 'sort_order', 'is_active', 'para_count'];
  const updates = [], params = [];
  for (const f of allowed) {
    if (req.body[f] !== undefined) {
      updates.push(`${f} = ?`);
      params.push(req.body[f]);
    }
  }
  if (!updates.length) return res.json({ ok: true });
  params.push(id);
  db.prepare(`UPDATE textbooks SET ${updates.join(', ')} WHERE id=?`).run(...params);
  res.json({ ok: true });
});

module.exports = router;
