const db = require('../db/db');
const { onLessonComplete } = require('./gamificationController');
const { stripTags } = require('../utils/sanitize');

/* ── helpers ──────────────────────────────────────────────────────────── */
function parseBlock(b) {
  let data = {};
  try { data = JSON.parse(b.data); } catch {}
  return { id: b.id, type: b.type, orderIndex: b.order_index, data };
}

// Estimate read time from blocks (words / 200 wpm)
// Accepts blocks with data already parsed as objects (not JSON strings)
function calcReadTime(blocks) {
  let words = 0;
  for (const b of blocks) {
    const d = (typeof b.data === 'string') ? (() => { try { return JSON.parse(b.data); } catch { return {}; } })() : (b.data || {});
    if (b.type === 'text')      words += (d.html || d.text || '').replace(/<[^>]+>/g, '').split(/\s+/).filter(Boolean).length;
    if (b.type === 'heading')   words += (d.text || '').split(/\s+/).filter(Boolean).length;
    if (b.type === 'quiz')      words += 8;
    if (b.type === 'accordion') words += (d.content || '').split(/\s+/).filter(Boolean).length;
    if (b.type === 'timeline' && Array.isArray(d.items))
      for (const it of d.items) words += ((it.title||'') + ' ' + (it.text||'')).split(/\s+/).filter(Boolean).length;
    if (b.type === 'geogebra' || b.type === 'diagram') words += 15;
    if (b.type === 'audio')     words += 30;
    if (b.type === 'video')     words += 30;
    if (b.type === 'alert')     words += (d.text || '').split(/\s+/).filter(Boolean).length;
    if (b.type === 'columns' && Array.isArray(d.cols))
      for (const col of d.cols) words += (col.content || '').replace(/<[^>]+>/g, '').split(/\s+/).filter(Boolean).length;
  }
  return Math.max(1, Math.ceil(words / 200));
}

/* ── GET /api/lessons/:id ─────────────────────────────────────────────── */
function get(req, res) {
  const role = req.user.role;
  const uid  = req.user.id;

  const row = db.prepare(`
    SELECT l.*, c.title AS course_title, c.is_published AS course_published
    FROM lessons l JOIN courses c ON c.id = l.course_id
    WHERE l.id = ?
  `).get(req.params.id);
  if (!row) return res.status(404).json({ error: 'Lesson not found' });
  if (role === 'student' && !row.is_published)
    return res.status(403).json({ error: 'Lesson not published' });
  if (role === 'student' && !row.course_published)
    return res.status(403).json({ error: 'Course not published' });
  const lesson = row;
  const course = { title: row.course_title };

  const blocks = db.prepare(
    'SELECT id, type, order_index, data FROM lesson_blocks WHERE lesson_id = ? ORDER BY order_index, id'
  ).all(lesson.id).map(parseBlock);

  const progress = db.prepare(
    'SELECT completed FROM lesson_progress WHERE user_id = ? AND lesson_id = ?'
  ).get(uid, lesson.id);

  const note = db.prepare(
    'SELECT text FROM lesson_notes WHERE user_id = ? AND lesson_id = ?'
  ).get(uid, lesson.id);

  // adjacent lessons
  const pubWhere = role === 'student' ? 'AND is_published = 1' : '';
  const siblings = db.prepare(`
    SELECT id, title FROM lessons WHERE course_id = ? ${pubWhere} ORDER BY order_index, id
  `).all(lesson.course_id);
  const idx  = siblings.findIndex(s => s.id === lesson.id);
  const prev = idx > 0 ? siblings[idx - 1] : null;
  const next = idx >= 0 && idx < siblings.length - 1 ? siblings[idx + 1] : null;

  res.json({
    id:          lesson.id,
    courseId:    lesson.course_id,
    courseTitle: course.title,
    title:       lesson.title,
    orderIndex:  lesson.order_index,
    isPublished: lesson.is_published === 1,
    sectionId:   lesson.section_id,
    readTime:    lesson.read_time || 0,
    blocks,
    completed:   progress?.completed === 1,
    note:        note?.text || '',
    prev:        prev ? { id: prev.id, title: prev.title } : null,
    next:        next ? { id: next.id, title: next.title } : null,
  });
}

/* ── POST /api/lessons ────────────────────────────────────────────────── */
function create(req, res) {
  const { courseId, title, orderIndex, sectionId } = req.body;
  if (!courseId || !title)
    return res.status(400).json({ error: 'courseId and title required' });
  if (!db.prepare('SELECT id FROM courses WHERE id = ?').get(courseId))
    return res.status(404).json({ error: 'Course not found' });

  const r = db.prepare(
    'INSERT INTO lessons (course_id, title, order_index, section_id) VALUES (?, ?, ?, ?)'
  ).run(courseId, title.trim(), orderIndex ?? 0, sectionId || null);
  res.status(201).json({ id: r.lastInsertRowid });
}

/* ── PUT /api/lessons/:id ─────────────────────────────────────────────── */
function update(req, res) {
  const lesson = db.prepare(`
    SELECT l.*, c.created_by AS course_owner
    FROM lessons l JOIN courses c ON c.id = l.course_id WHERE l.id = ?
  `).get(req.params.id);
  if (!lesson) return res.status(404).json({ error: 'Lesson not found' });
  if (req.user.role !== 'admin' && lesson.course_owner !== req.user.id)
    return res.status(403).json({ error: 'Forbidden' });
  const { title, orderIndex, isPublished, sectionId } = req.body;
  db.prepare(`
    UPDATE lessons SET title=?, order_index=?, is_published=?, section_id=? WHERE id=?
  `).run(
    title       ?? lesson.title,
    orderIndex  ?? lesson.order_index,
    isPublished !== undefined ? (isPublished ? 1 : 0) : lesson.is_published,
    sectionId   !== undefined ? (sectionId || null) : lesson.section_id,
    lesson.id
  );
  res.json({ ok: true });
}

/* ── DELETE /api/lessons/:id ──────────────────────────────────────────── */
function remove(req, res) {
  const lesson = db.prepare(`
    SELECT l.id, c.created_by AS course_owner
    FROM lessons l JOIN courses c ON c.id = l.course_id WHERE l.id = ?
  `).get(req.params.id);
  if (!lesson) return res.status(404).json({ error: 'Lesson not found' });
  if (req.user.role !== 'admin' && lesson.course_owner !== req.user.id)
    return res.status(403).json({ error: 'Forbidden' });
  db.prepare('DELETE FROM lessons WHERE id = ?').run(lesson.id);
  res.json({ ok: true });
}

/* ── PUT /api/lessons/:id/blocks ──────────────────────────────────────── */
function saveBlocks(req, res) {
  const lesson = db.prepare(`
    SELECT l.id, c.created_by AS course_owner
    FROM lessons l JOIN courses c ON c.id = l.course_id
    WHERE l.id = ?
  `).get(req.params.id);
  if (!lesson) return res.status(404).json({ error: 'Lesson not found' });
  if (req.user.role !== 'admin' && lesson.course_owner !== req.user.id)
    return res.status(403).json({ error: 'Forbidden' });

  const blocks = req.body.blocks;
  if (!Array.isArray(blocks))
    return res.status(400).json({ error: 'blocks must be an array' });

  const VALID_TYPES = ['heading','text','formula','image','quiz','sim','table','code','divider','callout','video','flashcard','matching','fill-blank','ordering','accordion','timeline','diagram','geogebra','audio','columns','alert'];

  db.transaction(() => {
    db.prepare('DELETE FROM lesson_blocks WHERE lesson_id = ?').run(lesson.id);
    const ins = db.prepare(
      'INSERT INTO lesson_blocks (lesson_id, type, order_index, data) VALUES (?, ?, ?, ?)'
    );
    blocks.forEach((b, i) => {
      const type = VALID_TYPES.includes(b.type) ? b.type : 'text';
      ins.run(lesson.id, type, b.orderIndex ?? i, JSON.stringify(b.data || {}));
    });

    // recalculate read time — pass already-parsed data objects, no double stringify/parse
    const rt = calcReadTime(blocks);
    db.prepare('UPDATE lessons SET read_time = ? WHERE id = ?').run(rt, lesson.id);
  })();

  res.json({ ok: true, count: blocks.length });
}

/* ── POST /api/lessons/:id/complete ──────────────────────────────────── */
function markComplete(req, res) {
  const lesson = db.prepare('SELECT * FROM lessons WHERE id = ?').get(req.params.id);
  if (!lesson) return res.status(404).json({ error: 'Lesson not found' });

  db.prepare(`
    INSERT INTO lesson_progress (user_id, lesson_id, completed, updated_at)
    VALUES (?, ?, 1, datetime('now'))
    ON CONFLICT (user_id, lesson_id) DO UPDATE SET completed=1, updated_at=datetime('now')
  `).run(req.user.id, lesson.id);

  const total = db.prepare(
    'SELECT COUNT(*) AS n FROM lessons WHERE course_id = ? AND is_published = 1'
  ).get(lesson.course_id).n;
  const done = db.prepare(`
    SELECT COUNT(*) AS n FROM lesson_progress lp
    JOIN lessons l ON lp.lesson_id = l.id
    WHERE l.course_id = ? AND lp.user_id = ? AND lp.completed = 1
  `).get(lesson.course_id, req.user.id).n;

  try { onLessonComplete(req.user.id, lesson.course_id); } catch {}
  res.json({ ok: true, courseComplete: done >= total && total > 0 });
}

/* ── PUT /api/lessons/:id/note ────────────────────────────────────────── */
function saveNote(req, res) {
  const lesson = db.prepare('SELECT id FROM lessons WHERE id = ?').get(req.params.id);
  if (!lesson) return res.status(404).json({ error: 'Lesson not found' });
  const text = (req.body.text || '').slice(0, 5000);
  db.prepare(`
    INSERT INTO lesson_notes (user_id, lesson_id, text, updated_at)
    VALUES (?, ?, ?, datetime('now'))
    ON CONFLICT (user_id, lesson_id) DO UPDATE SET text=excluded.text, updated_at=datetime('now')
  `).run(req.user.id, lesson.id, text);
  res.json({ ok: true });
}

/* ── GET /api/lessons/:id/comments ──────────────────────────────────── */
function listComments(req, res) {
  const lesson = db.prepare('SELECT id FROM lessons WHERE id = ?').get(req.params.id);
  if (!lesson) return res.status(404).json({ error: 'Lesson not found' });

  const rows = db.prepare(`
    SELECT c.id, c.lesson_id, c.user_id, c.parent_id, c.text, c.created_at,
      u.name AS user_name, u.role AS user_role
    FROM lesson_comments c
    JOIN users u ON c.user_id = u.id
    WHERE c.lesson_id = ?
    ORDER BY c.created_at ASC
  `).all(lesson.id);

  // build threaded structure: top-level + replies
  const top = [];
  const byId = {};
  rows.forEach(r => {
    const item = {
      id: r.id, lessonId: r.lesson_id, userId: r.user_id,
      parentId: r.parent_id, text: r.text, createdAt: r.created_at,
      userName: r.user_name, userRole: r.user_role,
      replies: [],
    };
    byId[r.id] = item;
    if (!r.parent_id) {
      top.push(item);
    } else if (byId[r.parent_id]) {
      byId[r.parent_id].replies.push(item);
    } else {
      top.push(item); // orphan → treat as top-level
    }
  });

  res.json(top);
}

/* ── POST /api/lessons/:id/comments ────────────────────────────────── */
function addComment(req, res) {
  const lesson = db.prepare('SELECT id FROM lessons WHERE id = ?').get(req.params.id);
  if (!lesson) return res.status(404).json({ error: 'Lesson not found' });

  const text = stripTags((req.body.text || '').trim());
  if (!text) return res.status(400).json({ error: 'text required' });
  if (text.length > 2000) return res.status(400).json({ error: 'Comment too long (max 2000)' });

  const parentId = req.body.parentId || null;
  if (parentId) {
    const parent = db.prepare('SELECT id FROM lesson_comments WHERE id = ? AND lesson_id = ?').get(parentId, lesson.id);
    if (!parent) return res.status(400).json({ error: 'Parent comment not found' });
  }

  const r = db.prepare(
    'INSERT INTO lesson_comments (lesson_id, user_id, parent_id, text) VALUES (?, ?, ?, ?)'
  ).run(lesson.id, req.user.id, parentId, text);

  // notify lesson author / teacher if comment is from student
  try {
    const course = db.prepare('SELECT created_by FROM courses WHERE id = (SELECT course_id FROM lessons WHERE id = ?)').get(lesson.id);
    if (course && course.created_by !== req.user.id) {
      const userName = db.prepare('SELECT name FROM users WHERE id = ?').get(req.user.id)?.name || 'Ученик';
      const lessonTitle = db.prepare('SELECT title FROM lessons WHERE id = ?').get(lesson.id)?.title || 'Урок';
      db.prepare(
        'INSERT INTO notifications (user_id, type, message, link) VALUES (?, ?, ?, ?)'
      ).run(course.created_by, 'comment', `${userName} оставил(а) комментарий к уроку «${lessonTitle}»`,
        `/lesson?id=${lesson.id}#comments`);
    }
  } catch {}

  res.status(201).json({ id: Number(r.lastInsertRowid) });
}

/* ── DELETE /api/lessons/:id/comments/:cid ─────────────────────────── */
function deleteComment(req, res) {
  const comment = db.prepare('SELECT * FROM lesson_comments WHERE id = ? AND lesson_id = ?').get(req.params.cid, req.params.id);
  if (!comment) return res.status(404).json({ error: 'Comment not found' });

  // only author or teacher/admin can delete
  const isOwner = comment.user_id === req.user.id;
  const isPrivileged = ['teacher', 'admin'].includes(req.user.role);
  if (!isOwner && !isPrivileged) return res.status(403).json({ error: 'Forbidden' });

  db.prepare('DELETE FROM lesson_comments WHERE id = ?').run(comment.id);
  res.json({ ok: true });
}

module.exports = { get, create, update, remove, saveBlocks, markComplete, saveNote, listComments, addComment, deleteComment };
