// ============================================================
// LEARNING ADMIN ROUTES — CMS for categories, content, quizzes
// ============================================================

var express = require('express');
var router = express.Router();
var db = require('../db/database');
var { authMiddleware, moderatorMiddleware } = require('../middleware/auth');
var { generateContentEmbedding, isEmbeddingsAvailable } = require('../utils/embeddings');

router.use(authMiddleware);
router.use(moderatorMiddleware);

// ── Helpers ──────────────────────────────────────────────────
function slugify(text) {
  return text.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').substring(0, 100);
}

var ALLOWED_SLUG_TABLES = ['learning_categories', 'learning_content'];

async function uniqueSlug(table, base) {
  if (ALLOWED_SLUG_TABLES.indexOf(table) === -1) throw new Error('Invalid table for slug generation');
  var slug = slugify(base);
  var exists = await db.get('SELECT id FROM ' + table + ' WHERE slug = ?', [slug]);
  if (!exists) return slug;
  var i = 2;
  while (true) {
    var attempt = slug + '-' + i;
    var exists2 = await db.get('SELECT id FROM ' + table + ' WHERE slug = ?', [attempt]);
    if (!exists2) return attempt;
    i++;
    if (i > 100) return slug + '-' + Date.now();
  }
}

// ============================================================
// CATEGORIES — CRUD
// ============================================================

router.get('/categories', async function(req, res) {
  try {
    var categories = await db.all(
      `SELECT c.*, (SELECT COUNT(*) FROM learning_content lc WHERE lc.category_id = c.id) as content_count
       FROM learning_categories c ORDER BY c.sort_order ASC, c.name ASC`,
      []
    );
    res.json({ success: true, categories: categories });
  } catch (err) { console.error('[LearningAdmin]', err.message); res.status(500).json({ error: 'Internal server error' }); }
});

router.post('/categories', async function(req, res) {
  try {
    var { name, description, sort_order } = req.body;
    if (!name || !name.trim()) return res.status(400).json({ error: 'Name required' });

    var existing = await db.get('SELECT id, slug FROM learning_categories WHERE LOWER(name) = LOWER(?)', [name.trim()]);
    if (existing) return res.json({ success: true, id: existing.id, slug: existing.slug, existing: true });

    var slug = await uniqueSlug('learning_categories', name.trim());

    var result = await db.run(
      'INSERT INTO learning_categories (name, slug, description, sort_order) VALUES (?, ?, ?, ?)',
      [name.trim(), slug, description || '', sort_order || 0]
    );

    res.json({ success: true, id: result.lastInsertRowid, slug: slug });
  } catch (err) { console.error('[LearningAdmin]', err.message); res.status(500).json({ error: 'Internal server error' }); }
});

router.put('/categories/:id', async function(req, res) {
  try {
    var { name, description, sort_order } = req.body;
    var cat = await db.get('SELECT * FROM learning_categories WHERE id = ?', [req.params.id]);
    if (!cat) return res.status(404).json({ error: 'Category not found' });

    await db.run(
      'UPDATE learning_categories SET name = ?, description = ?, sort_order = ? WHERE id = ?',
      [name || cat.name, description !== undefined ? description : cat.description, sort_order !== undefined ? sort_order : cat.sort_order, cat.id]
    );

    res.json({ success: true });
  } catch (err) { console.error('[LearningAdmin]', err.message); res.status(500).json({ error: 'Internal server error' }); }
});

router.delete('/categories/:id', async function(req, res) {
  try {
    // Set content in this category to uncategorized (NULL)
    await db.run('UPDATE learning_content SET category_id = NULL WHERE category_id = ?', [req.params.id]);
    await db.run('DELETE FROM learning_categories WHERE id = ?', [req.params.id]);
    res.json({ success: true });
  } catch (err) { console.error('[LearningAdmin]', err.message); res.status(500).json({ error: 'Internal server error' }); }
});

// ============================================================
// CONTENT — CRUD
// ============================================================

router.get('/content', async function(req, res) {
  try {
    var content = await db.all(
      `SELECT c.id, c.title, c.slug, c.subject, c.content_type, c.published, c.category_id,
              c.created_at, c.updated_at,
              cat.name as category_name,
              u.name as author_name,
              (SELECT COUNT(*) FROM learning_questions q WHERE q.content_id = c.id) as question_count
       FROM learning_content c
       LEFT JOIN learning_categories cat ON c.category_id = cat.id
       LEFT JOIN users u ON c.author_id = u.id
       ORDER BY c.updated_at DESC`,
      []
    );
    res.json({ success: true, content: content });
  } catch (err) { console.error('[LearningAdmin]', err.message); res.status(500).json({ error: 'Internal server error' }); }
});

router.get('/content/:id', async function(req, res) {
  try {
    var item = await db.get(
      `SELECT c.*, cat.name as category_name
       FROM learning_content c
       LEFT JOIN learning_categories cat ON c.category_id = cat.id
       WHERE c.id = ?`,
      [req.params.id]
    );
    if (!item) return res.status(404).json({ error: 'Content not found' });

    // Get questions + options
    var questions = await db.all(
      'SELECT * FROM learning_questions WHERE content_id = ? ORDER BY sort_order ASC',
      [item.id]
    );
    for (var i = 0; i < questions.length; i++) {
      questions[i].options = await db.all(
        'SELECT * FROM learning_options WHERE question_id = ? ORDER BY sort_order ASC',
        [questions[i].id]
      );
    }
    item.questions = questions;

    res.json({ success: true, content: item });
  } catch (err) { console.error('[LearningAdmin]', err.message); res.status(500).json({ error: 'Internal server error' }); }
});

router.post('/content', async function(req, res) {
  try {
    var { title, body, category_id, subject, content_type, published } = req.body;
    if (!title || !title.trim()) return res.status(400).json({ error: 'Title required' });

    var slug = await uniqueSlug('learning_content', title.trim());

    var result = await db.run(
      'INSERT INTO learning_content (title, slug, body, category_id, subject, content_type, published, author_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
      [title.trim(), slug, body || '', category_id || null, subject || '', content_type || 'article', published ? true : false, req.user.id]
    );

    var contentId = result.lastInsertRowid;

    // Generate embedding asynchronously (don't block response)
    if (isEmbeddingsAvailable() && body && body.trim()) {
      generateContentEmbedding({ title: title.trim(), subject: subject || '', body: body })
        .then(function(embedding) {
          return db.query(
            'UPDATE learning_content SET embedding = $1 WHERE id = $2',
            [JSON.stringify(embedding), contentId]
          );
        })
        .then(function() { console.log('[Embeddings] Generated for content ID:', contentId); })
        .catch(function(err) { console.error('[Embeddings] Failed for content ID ' + contentId + ':', err.message); });
    }

    res.json({ success: true, id: contentId, slug: slug });
  } catch (err) { console.error('[LearningAdmin]', err.message); res.status(500).json({ error: 'Internal server error' }); }
});

router.put('/content/:id', async function(req, res) {
  try {
    var item = await db.get('SELECT * FROM learning_content WHERE id = ?', [req.params.id]);
    if (!item) return res.status(404).json({ error: 'Content not found' });

    var { title, body, category_id, subject, content_type, published } = req.body;

    var newTitle = title !== undefined ? title : item.title;
    var newBody = body !== undefined ? body : item.body;
    var newSubject = subject !== undefined ? subject : item.subject;

    await db.run(
      'UPDATE learning_content SET title = ?, body = ?, category_id = ?, subject = ?, content_type = ?, published = ?, updated_at = NOW() WHERE id = ?',
      [
        newTitle,
        newBody,
        category_id !== undefined ? (category_id || null) : item.category_id,
        newSubject,
        content_type !== undefined ? content_type : item.content_type,
        published !== undefined ? published : item.published,
        item.id
      ]
    );

    // Regenerate embedding if title/body/subject changed (async, don't block)
    if (isEmbeddingsAvailable() && (title !== undefined || body !== undefined || subject !== undefined)) {
      if (newBody && newBody.trim()) {
        generateContentEmbedding({ title: newTitle, subject: newSubject, body: newBody })
          .then(function(embedding) {
            return db.query(
              'UPDATE learning_content SET embedding = $1 WHERE id = $2',
              [JSON.stringify(embedding), item.id]
            );
          })
          .then(function() { console.log('[Embeddings] Regenerated for content ID:', item.id); })
          .catch(function(err) { console.error('[Embeddings] Failed to regenerate for content ID ' + item.id + ':', err.message); });
      }
    }

    res.json({ success: true });
  } catch (err) { console.error('[LearningAdmin]', err.message); res.status(500).json({ error: 'Internal server error' }); }
});

router.delete('/content/:id', async function(req, res) {
  try {
    await db.run('DELETE FROM learning_content WHERE id = ?', [req.params.id]);
    res.json({ success: true });
  } catch (err) { console.error('[LearningAdmin]', err.message); res.status(500).json({ error: 'Internal server error' }); }
});

// ============================================================
// QUESTIONS — CRUD (nested under content)
// ============================================================

router.post('/content/:contentId/questions', async function(req, res) {
  try {
    var { question_text, question_type, explanation, options } = req.body;
    if (!question_text) return res.status(400).json({ error: 'Question text required' });

    // Get max sort_order
    var maxOrder = await db.get('SELECT COALESCE(MAX(sort_order), -1) as mx FROM learning_questions WHERE content_id = ?', [req.params.contentId]);
    var sortOrder = (maxOrder ? maxOrder.mx : -1) + 1;

    var result = await db.run(
      'INSERT INTO learning_questions (content_id, question_text, question_type, explanation, sort_order) VALUES (?, ?, ?, ?, ?)',
      [req.params.contentId, question_text, question_type || 'mcq', explanation || '', sortOrder]
    );

    var questionId = result.lastInsertRowid;

    // Insert options if provided
    if (options && Array.isArray(options)) {
      for (var i = 0; i < options.length; i++) {
        var opt = options[i];
        await db.run(
          'INSERT INTO learning_options (question_id, option_text, is_correct, explanation, sort_order) VALUES (?, ?, ?, ?, ?)',
          [questionId, opt.option_text, opt.is_correct ? true : false, opt.explanation || '', i]
        );
      }
    }

    res.json({ success: true, id: questionId });
  } catch (err) { console.error('[LearningAdmin]', err.message); res.status(500).json({ error: 'Internal server error' }); }
});

router.put('/questions/:id', async function(req, res) {
  try {
    var q = await db.get('SELECT * FROM learning_questions WHERE id = ?', [req.params.id]);
    if (!q) return res.status(404).json({ error: 'Question not found' });

    var { question_text, question_type, explanation, options } = req.body;

    await db.run(
      'UPDATE learning_questions SET question_text = ?, question_type = ?, explanation = ? WHERE id = ?',
      [question_text || q.question_text, question_type || q.question_type, explanation !== undefined ? explanation : q.explanation, q.id]
    );

    // Replace options if provided
    if (options && Array.isArray(options)) {
      await db.run('DELETE FROM learning_options WHERE question_id = ?', [q.id]);
      for (var i = 0; i < options.length; i++) {
        var opt = options[i];
        await db.run(
          'INSERT INTO learning_options (question_id, option_text, is_correct, explanation, sort_order) VALUES (?, ?, ?, ?, ?)',
          [q.id, opt.option_text, opt.is_correct ? true : false, opt.explanation || '', i]
        );
      }
    }

    res.json({ success: true });
  } catch (err) { console.error('[LearningAdmin]', err.message); res.status(500).json({ error: 'Internal server error' }); }
});

router.delete('/questions/:id', async function(req, res) {
  try {
    await db.run('DELETE FROM learning_questions WHERE id = ?', [req.params.id]);
    res.json({ success: true });
  } catch (err) { console.error('[LearningAdmin]', err.message); res.status(500).json({ error: 'Internal server error' }); }
});

// ============================================================
// STATS
// ============================================================
router.get('/stats', async function(req, res) {
  try {
    var totalContent = await db.get('SELECT COUNT(*) as count FROM learning_content', []);
    var published = await db.get('SELECT COUNT(*) as count FROM learning_content WHERE published = true', []);
    var totalCategories = await db.get('SELECT COUNT(*) as count FROM learning_categories', []);
    var totalQuizzes = await db.get("SELECT COUNT(DISTINCT content_id) as count FROM learning_questions", []);
    var totalAttempts = await db.get('SELECT COUNT(*) as count FROM learning_progress', []);
    var withEmbeddings = await db.get('SELECT COUNT(*) as count FROM learning_content WHERE embedding IS NOT NULL', []);

    res.json({
      success: true,
      stats: {
        totalContent: parseInt(totalContent.count),
        publishedContent: parseInt(published.count),
        totalCategories: parseInt(totalCategories.count),
        totalQuizzes: parseInt(totalQuizzes.count),
        totalAttempts: parseInt(totalAttempts.count),
        withEmbeddings: parseInt(withEmbeddings.count),
        embeddingsEnabled: isEmbeddingsAvailable()
      }
    });
  } catch (err) { console.error('[LearningAdmin]', err.message); res.status(500).json({ error: 'Internal server error' }); }
});

// ============================================================
// EMBEDDINGS — Backfill & Management
// ============================================================

// Generate embeddings for all content (or just missing ones)
router.post('/embeddings/generate', async function(req, res) {
  try {
    if (!isEmbeddingsAvailable()) {
      return res.status(400).json({ error: 'Embeddings not configured. Set LITELLM_API_BASE, VERTEX_PROJECT, or OPENAI_API_KEY' });
    }

    var { regenerateAll } = req.body;

    // Get content without embeddings (or all if regenerateAll=true)
    var whereClause = regenerateAll ? '' : 'WHERE embedding IS NULL';
    var content = await db.all(
      'SELECT id, title, subject, body FROM learning_content ' + whereClause + ' ORDER BY id ASC',
      []
    );

    if (content.length === 0) {
      return res.json({ success: true, message: 'All content already has embeddings', processed: 0 });
    }

    // Process in background
    var processed = 0;
    var failed = 0;

    console.log('[Embeddings] Starting batch generation for ' + content.length + ' items...');

    // Don't await — run in background
    async function generateEmbeddingsInBackground() {
      for (var i = 0; i < content.length; i++) {
        var item = content[i];
        try {
          if (!item.body || !item.body.trim()) {
            console.log('[Embeddings] Skipping empty content ID:', item.id);
            continue;
          }
          var embedding = await generateContentEmbedding(item);
          await db.query(
            'UPDATE learning_content SET embedding = $1 WHERE id = $2',
            [JSON.stringify(embedding), item.id]
          );
          processed++;
          console.log('[Embeddings] Generated ' + processed + '/' + content.length + ' (ID: ' + item.id + ')');
        } catch (err) {
          failed++;
          console.error('[Embeddings] Failed for content ID ' + item.id + ':', err.message);
        }
      }
      console.log('[Embeddings] Batch complete: ' + processed + ' succeeded, ' + failed + ' failed');

      // Create index if we have enough embeddings now
      if (processed >= 10) {
        try {
          var lists = Math.max(10, Math.floor(Math.sqrt(processed)));
          await db.query(
            'CREATE INDEX IF NOT EXISTS idx_learning_content_embedding ON learning_content USING ivfflat (embedding vector_cosine_ops) WITH (lists = ' + lists + ')'
          );
          console.log('[Embeddings] Vector index created/updated');
        } catch (e) {
          console.error('[Embeddings] Index creation failed:', e.message);
        }
      }
    }
    generateEmbeddingsInBackground();

    res.json({
      success: true,
      message: 'Embedding generation started in background',
      total: content.length
    });

  } catch (err) {
    console.error('[LearningAdmin]', err.message);
    res.status(500).json({ error: 'Request failed' });
  }
});

// Check embedding status
router.get('/embeddings/status', async function(req, res) {
  try {
    var total = await db.get('SELECT COUNT(*) as count FROM learning_content', []);
    var withEmbeddings = await db.get('SELECT COUNT(*) as count FROM learning_content WHERE embedding IS NOT NULL', []);
    var missing = parseInt(total.count) - parseInt(withEmbeddings.count);

    res.json({
      success: true,
      enabled: isEmbeddingsAvailable(),
      total: parseInt(total.count),
      withEmbeddings: parseInt(withEmbeddings.count),
      missing: missing,
      model: process.env.EMBEDDING_MODEL || 'vertex_ai/text-embedding-005',
      dimensions: parseInt(process.env.EMBEDDING_DIMENSIONS) || 768
    });
  } catch (err) {
    res.status(500).json({ error: 'Request failed' });
  }
});

module.exports = router;
