/**
 * Online Exams Module - Complete Vertical Slice
 * Backend API Controller
 */

const { v4: uuidv4 } = require('uuid');
const express = require('express');
const path = require('path');
const router = express.Router();

const dbPath = process.env.DB_PATH || path.join(__dirname, '../../data/school.db');
const Database = require('better-sqlite3');
const db = new Database(dbPath);
db.pragma('foreign_keys = ON');

// Auth middleware
const auth = (req, res, next) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).json({ error: 'No token provided' });
  try {
    req.user = require('jsonwebtoken').verify(token, process.env.JWT_SECRET || 'africa-alert-secret-key-2024');
    next();
  } catch (err) {
    res.status(401).json({ error: 'Invalid token' });
  }
};

// Helper to set sync status
const setSyncPending = (table, id) => {
  try {
    db.prepare(`UPDATE ${table} SET sync_status = 'pending' WHERE id = ?`).run(id);
  } catch (e) {}
};

// ============ EXAM GROUPS ============

// List all exam groups
router.get('/groups', auth, (req, res) => {
  const { subject_id, exam_type, academic_year } = req.query;
  
  let query = `
    SELECT eg.*, 
      (SELECT COUNT(*) FROM question_banks WHERE exam_group_id = eg.id AND is_deleted = 0) as question_count,
      (SELECT COUNT(*) FROM exam_schedules WHERE exam_group_id = eg.id AND is_deleted = 0) as schedule_count
    FROM exam_groups eg
    WHERE eg.is_deleted = 0
  `;
  const params = [];
  
  if (subject_id) { query += ' AND eg.id IN (SELECT exam_group_id FROM question_banks WHERE subject_id = ?)'; params.push(subject_id); }
  if (exam_type) { query += ' AND eg.exam_type = ?'; params.push(exam_type); }
  if (academic_year) { query += ' AND eg.academic_year = ?'; params.push(academic_year); }
  
  query += ' ORDER BY eg.created_at DESC';
  
  const groups = db.prepare(query).all(...params);
  res.json(groups);
});

// Get single exam group
router.get('/groups/:id', auth, (req, res) => {
  const group = db.prepare(`
    SELECT eg.*,
      (SELECT COUNT(*) FROM question_banks WHERE exam_group_id = eg.id AND is_deleted = 0) as question_count
    FROM exam_groups eg
    WHERE eg.id = ? AND eg.is_deleted = 0
  `).get(req.params.id);
  
  if (!group) return res.status(404).json({ error: 'Exam group not found' });
  
  // Get questions
  const questions = db.prepare(`
    SELECT * FROM question_banks 
    WHERE exam_group_id = ? AND is_deleted = 0
    ORDER BY difficulty, id
  `).all(req.params.id);
  
  // Get schedules
  const schedules = db.prepare(`
    SELECT es.*, c.name as class_name, s.name as subject_name
    FROM exam_schedules es
    LEFT JOIN classes c ON es.class_id = c.id
    LEFT JOIN subjects s ON es.subject_id = s.id
    WHERE es.exam_group_id = ? AND es.is_deleted = 0
    ORDER BY es.start_time
  `).all(req.params.id);
  
  res.json({ ...group, questions, schedules });
});

// Create exam group
router.post('/groups', auth, (req, res) => {
  const { name, description, exam_type, duration_minutes, total_marks, passing_marks, is_random_order, show_results, allow_review, max_attempts, academic_year, term } = req.body;
  
  const uid = uuidv4();
  
  try {
    const result = db.prepare(`
      INSERT INTO exam_groups (uid, name, description, exam_type, duration_minutes, total_marks, passing_marks, is_random_order, show_results, allow_review, max_attempts, academic_year, term)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    `).run(uid, name, description, exam_type, duration_minutes || 60, total_marks || 100, passing_marks || 50, is_random_order ? 1 : 0, show_results ? 1 : 0, allow_review ? 1 : 0, max_attempts || 1, academic_year, term);
    
    const group = db.prepare('SELECT * FROM exam_groups WHERE id = ?').get(result.lastInsertRowid);
    res.status(201).json(group);
    
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

// Update exam group
router.put('/groups/:id', auth, (req, res) => {
  const { name, description, exam_type, duration_minutes, total_marks, passing_marks, is_random_order, show_results, allow_review, max_attempts } = req.body;
  
  try {
    db.prepare(`
      UPDATE exam_groups SET
        name = COALESCE(?, name),
        description = COALESCE(?, description),
        exam_type = COALESCE(?, exam_type),
        duration_minutes = COALESCE(?, duration_minutes),
        total_marks = COALESCE(?, total_marks),
        passing_marks = COALESCE(?, passing_marks),
        is_random_order = COALESCE(?, is_random_order),
        show_results = COALESCE(?, show_results),
        allow_review = COALESCE(?, allow_review),
        max_attempts = COALESCE(?, max_attempts),
        updated_at = CURRENT_TIMESTAMP,
        sync_status = 'pending'
      WHERE id = ? AND is_deleted = 0
    `).run(name, description, exam_type, duration_minutes, total_marks, passing_marks, is_random_order, show_results, allow_review, max_attempts, req.params.id);
    
    const group = db.prepare('SELECT * FROM exam_groups WHERE id = ?').get(req.params.id);
    res.json(group);
    
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

// Delete exam group (soft delete)
router.delete('/groups/:id', auth, (req, res) => {
  db.prepare(`
    UPDATE exam_groups SET is_deleted = 1, sync_status = 'pending', updated_at = CURRENT_TIMESTAMP
    WHERE id = ?
  `).run(req.params.id);
  res.json({ success: true });
});

// ============ QUESTION BANKS ============

// List questions
router.get('/questions', auth, (req, res) => {
  const { exam_group_id, subject_id, difficulty } = req.query;
  
  let query = 'SELECT * FROM question_banks WHERE is_deleted = 0';
  const params = [];
  
  if (exam_group_id) { query += ' AND exam_group_id = ?'; params.push(exam_group_id); }
  if (subject_id) { query += ' AND subject_id = ?'; params.push(subject_id); }
  if (difficulty) { query += ' AND difficulty = ?'; params.push(difficulty); }
  
  query += ' ORDER BY created_at DESC';
  
  const questions = db.prepare(query).all(...params);
  res.json(questions);
});

// Create question
router.post('/questions', auth, (req, res) => {
  const { exam_group_id, subject_id, question_type, question, options, correct_answer, marks, difficulty, tags } = req.body;
  
  const uid = uuidv4();
  const optionsJson = options ? JSON.stringify(options) : null;
  
  try {
    const result = db.prepare(`
      INSERT INTO question_banks (uid, exam_group_id, subject_id, question_type, question, options, correct_answer, marks, difficulty, tags)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    `).run(uid, exam_group_id, subject_id, question_type, question, optionsJson, correct_answer, marks || 1, difficulty || 'medium', tags);
    
    const q = db.prepare('SELECT * FROM question_banks WHERE id = ?').get(result.lastInsertRowid);
    res.status(201).json(q);
    
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

// Bulk create questions
router.post('/questions/bulk', auth, (req, res) => {
  const { questions } = req.body;
  
  if (!Array.isArray(questions) || questions.length === 0) {
    return res.status(400).json({ error: 'Questions array required' });
  }
  
  const insert = db.prepare(`
    INSERT INTO question_banks (uid, exam_group_id, subject_id, question_type, question, options, correct_answer, marks, difficulty, tags)
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  `);
  
  const insertMany = db.transaction((questions) => {
    const inserted = [];
    for (const q of questions) {
      const uid = uuidv4();
      const optionsJson = q.options ? JSON.stringify(q.options) : null;
      insert.run(uid, q.exam_group_id, q.subject_id, q.question_type, q.question, optionsJson, q.correct_answer, q.marks || 1, q.difficulty || 'medium', q.tags);
      inserted.push({ uid, id: insert.lastInsertRowid });
    }
    return inserted;
  });
  
  try {
    const result = insertMany(questions);
    res.status(201).json({ created: result.length, questions: result });
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

// Update question
router.put('/questions/:id', auth, (req, res) => {
  const { question, options, correct_answer, marks, difficulty, tags } = req.body;
  const optionsJson = options ? JSON.stringify(options) : null;
  
  try {
    db.prepare(`
      UPDATE question_banks SET
        question = COALESCE(?, question),
        options = COALESCE(?, options),
        correct_answer = COALESCE(?, correct_answer),
        marks = COALESCE(?, marks),
        difficulty = COALESCE(?, difficulty),
        tags = COALESCE(?, tags),
        updated_at = CURRENT_TIMESTAMP,
        sync_status = 'pending'
      WHERE id = ? AND is_deleted = 0
    `).run(question, optionsJson, correct_answer, marks, difficulty, tags, req.params.id);
    
    const q = db.prepare('SELECT * FROM question_banks WHERE id = ?').get(req.params.id);
    res.json(q);
    
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

// Delete question
router.delete('/questions/:id', auth, (req, res) => {
  db.prepare(`
    UPDATE question_banks SET is_deleted = 1, sync_status = 'pending', updated_at = CURRENT_TIMESTAMP
    WHERE id = ?
  `).run(req.params.id);
  res.json({ success: true });
});

// ============ EXAM SCHEDULES ============

// List schedules
router.get('/schedules', auth, (req, res) => {
  const { class_id, exam_group_id, is_active } = req.query;
  
  let query = `
    SELECT es.*, eg.name as exam_name, eg.exam_type, eg.duration_minutes,
      c.name as class_name, s.name as subject_name
    FROM exam_schedules es
    JOIN exam_groups eg ON es.exam_group_id = eg.id
    LEFT JOIN classes c ON es.class_id = c.id
    LEFT JOIN subjects s ON es.subject_id = s.id
    WHERE es.is_deleted = 0
  `;
  const params = [];
  
  if (class_id) { query += ' AND es.class_id = ?'; params.push(class_id); }
  if (exam_group_id) { query += ' AND es.exam_group_id = ?'; params.push(exam_group_id); }
  if (is_active !== undefined) { query += ' AND es.is_active = ?'; params.push(is_active ? 1 : 0); }
  
  query += ' ORDER BY es.start_time DESC';
  
  const schedules = db.prepare(query).all(...params);
  res.json(schedules);
});

// Create schedule
router.post('/schedules', auth, (req, res) => {
  const { exam_group_id, class_id, subject_id, start_time, end_time, duration_minutes, instructions } = req.body;
  
  const uid = uuidv4();
  
  try {
    const result = db.prepare(`
      INSERT INTO exam_schedules (uid, exam_group_id, class_id, subject_id, start_time, end_time, duration_minutes, instructions)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    `).run(uid, exam_group_id, class_id, subject_id, start_time, end_time, duration_minutes, instructions);
    
    const schedule = db.prepare('SELECT * FROM exam_schedules WHERE id = ?').get(result.lastInsertRowid);
    res.status(201).json(schedule);
    
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

// ============ EXAM ATTEMPTS ============

// Get available exams for student
router.get('/available', auth, (req, res) => {
  const studentId = req.user.id;
  const now = new Date().toISOString();
  
  // Get student's enrolled classes
  const enrollments = db.prepare(`
    SELECT class_id FROM enrollments 
    WHERE student_id = ? AND status = 'active'
  `).all(studentId);
  const classIds = enrollments.map(e => e.class_id);
  
  if (classIds.length === 0) {
    return res.json([]);
  }
  
  // Get available scheduled exams
  const placeholders = classIds.map(() => '?').join(',');
  const schedules = db.prepare(`
    SELECT es.*, eg.name as exam_name, eg.exam_type, eg.duration_minutes, eg.total_marks, eg.max_attempts,
      s.name as subject_name,
      (SELECT COUNT(*) FROM exam_attempts WHERE exam_group_id = eg.id AND student_id = ? AND status != 'in-progress') as attempts_taken
    FROM exam_schedules es
    JOIN exam_groups eg ON es.exam_group_id = eg.id
    LEFT JOIN subjects s ON es.subject_id = s.id
    WHERE es.class_id IN (${placeholders})
      AND es.is_active = 1
      AND es.start_time <= ?
    ORDER BY es.start_time
  `).all(studentId, now, ...classIds);
  
  res.json(schedules);
});

// Start exam attempt
router.post('/attempts/start', auth, (req, res) => {
  const studentId = req.user.id;
  const { exam_group_id, schedule_id } = req.body;
  
  // Check max attempts
  const existingAttempts = db.prepare(`
    SELECT COUNT(*) as count FROM exam_attempts 
    WHERE exam_group_id = ? AND student_id = ? AND status != 'in-progress'
  `).get(exam_group_id, studentId);
  
  const examGroup = db.prepare('SELECT * FROM exam_groups WHERE id = ?').get(exam_group_id);
  if (!examGroup) return res.status(404).json({ error: 'Exam not found' });
  
  if (existingAttempts.count >= examGroup.max_attempts) {
    return res.status(400).json({ error: 'Maximum attempts reached' });
  }
  
  // Check existing in-progress attempt
  const inProgress = db.prepare(`
    SELECT * FROM exam_attempts 
    WHERE exam_group_id = ? AND student_id = ? AND status = 'in-progress'
    ORDER BY started_at DESC LIMIT 1
  `).get(exam_group_id, studentId);
  
  if (inProgress) {
    // Return existing attempt
    const questions = db.prepare(`
      SELECT * FROM question_banks 
      WHERE exam_group_id = ? AND is_deleted = 0
      ORDER BY ${examGroup.is_random_order ? 'RANDOM()' : 'id'}
    `).all(exam_group_id);
    
    return res.json({ ...inProgress, questions });
  }
  
  // Create new attempt
  const uid = uuidv4();
  
  const result = db.prepare(`
    INSERT INTO exam_attempts (uid, student_id, exam_group_id, schedule_id, started_at)
    VALUES (?, ?, ?, ?, ?)
  `).run(uid, studentId, exam_group_id, schedule_id, new Date().toISOString());
  
  const attempt = db.prepare('SELECT * FROM exam_attempts WHERE id = ?').get(result.lastInsertRowid);
  
  // Get questions (without correct answers for security)
  const questions = db.prepare(`
    SELECT id, question_type, question, options, marks, difficulty
    FROM question_banks 
    WHERE exam_group_id = ? AND is_deleted = 0
    ORDER BY ${examGroup.is_random_order ? 'RANDOM()' : 'id'}
  `).all(exam_group_id);
  
  // Parse options for frontend
  const processedQuestions = questions.map(q => ({
    ...q,
    options: q.options ? JSON.parse(q.options) : null
  }));
  
  res.status(201).json({ ...attempt, questions: processedQuestions });
});

// Save answer
router.post('/attempts/:attemptId/answer', auth, (req, res) => {
  const { question_id, answer } = req.body;
  const attemptId = req.params.attemptId;
  
  const uid = uuidv4();
  
  try {
    // Upsert answer
    const existing = db.prepare('SELECT id FROM exam_answers WHERE attempt_id = ? AND question_id = ?').get(attemptId, question_id);
    
    if (existing) {
      db.prepare(`
        UPDATE exam_answers SET answer = ?, answered_at = CURRENT_TIMESTAMP
        WHERE id = ?
      `).run(answer, existing.id);
    } else {
      db.prepare(`
        INSERT INTO exam_answers (uid, attempt_id, question_id, answer, answered_at)
        VALUES (?, ?, ?, ?, ?)
      `).run(uid, attemptId, question_id, answer, new Date().toISOString());
    }
    
    res.json({ success: true });
    
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

// Submit exam
router.post('/attempts/:attemptId/submit', auth, (req, res) => {
  const attemptId = req.params.attemptId;
  
  // Get attempt
  const attempt = db.prepare(`
    SELECT ea.*, eg.correct_answer as exam_correct
    FROM exam_attempts ea
    JOIN exam_groups eg ON ea.exam_group_id = eg.id
    WHERE ea.id = ?
  `).get(attemptId);
  
  if (!attempt) return res.status(404).json({ error: 'Attempt not found' });
  
  // Get all questions and answers
  const questions = db.prepare('SELECT * FROM question_banks WHERE exam_group_id = ?').all(attempt.exam_group_id);
  const answers = db.prepare('SELECT * FROM exam_answers WHERE attempt_id = ?').all(attemptId);
  
  // Grade the exam
  let totalMarks = 0;
  let obtainedMarks = 0;
  
  const answerMap = {};
  answers.forEach(a => { answerMap[a.question_id] = a; });
  
  for (const question of questions) {
    totalMarks += question.marks || 0;
    const answer = answerMap[question.id];
    
    if (answer) {
      const correctAnswer = question.correct_answer;
      const studentAnswer = answer.answer;
      
      // Check if correct (case-insensitive for short answers)
      let isCorrect = false;
      if (question.question_type === 'multiple-choice' || question.question_type === 'true-false') {
        isCorrect = studentAnswer === correctAnswer;
      } else {
        isCorrect = studentAnswer?.toLowerCase().trim() === correctAnswer?.toLowerCase().trim();
      }
      
      // Update answer with grading
      db.prepare(`
        UPDATE exam_answers SET is_correct = ?, marks_obtained = ?
        WHERE id = ?
      `).run(isCorrect ? 1 : 0, isCorrect ? question.marks : 0, answer.id);
      
      if (isCorrect) {
        obtainedMarks += question.marks || 0;
      }
    }
  }
  
  const percentage = totalMarks > 0 ? (obtainedMarks / totalMarks) * 100 : 0;
  const timeSpent = Math.floor((new Date() - new Date(attempt.started_at)) / 1000);
  
  // Update attempt
  db.prepare(`
    UPDATE exam_attempts SET
      submitted_at = CURRENT_TIMESTAMP,
      time_spent_seconds = ?,
      total_marks = ?,
      obtained_marks = ?,
      percentage = ?,
      status = 'submitted',
      ip_address = ?,
      user_agent = ?,
      updated_at = CURRENT_TIMESTAMP,
      sync_status = 'pending'
    WHERE id = ?
  `).run(
    timeSpent,
    totalMarks,
    obtainedMarks,
    percentage,
    req.ip,
    req.get('user-agent'),
    attemptId
  );
  
  const updatedAttempt = db.prepare('SELECT * FROM exam_attempts WHERE id = ?').get(attemptId);
  
  res.json({
    ...updatedAttempt,
    questions: questions, // Include for review if allowed
    correctAnswers: questions.map(q => ({ question_id: q.id, correct_answer: q.correct_answer, marks: q.marks }))
  });
});

// Get attempt results
router.get('/attempts/:attemptId', auth, (req, res) => {
  const attempt = db.prepare(`
    SELECT ea.*, eg.name as exam_name, eg.show_results, eg.allow_review
    FROM exam_attempts ea
    JOIN exam_groups eg ON ea.exam_group_id = eg.id
    WHERE ea.id = ?
  `).get(req.params.attemptId);
  
  if (!attempt) return res.status(404).json({ error: 'Attempt not found' });
  
  // Get answers with questions
  const answers = db.prepare(`
    SELECT qa.*, qb.question, qb.correct_answer, qb.marks as question_marks, qb.options as question_options
    FROM exam_answers qa
    JOIN question_banks qb ON qa.question_id = qb.id
    WHERE qa.attempt_id = ?
  `).all(req.params.attemptId);
  
  res.json({
    ...attempt,
    answers: answers.map(a => ({
      ...a,
      question_options: a.question_options ? JSON.parse(a.question_options) : null
    }))
  });
});

// Get student's attempt history
router.get('/attempts', auth, (req, res) => {
  const studentId = req.user.id;
  const { exam_group_id } = req.query;
  
  let query = `
    SELECT ea.*, eg.name as exam_name, eg.exam_type, eg.total_marks, eg.passing_marks
    FROM exam_attempts ea
    JOIN exam_groups eg ON ea.exam_group_id = eg.id
    WHERE ea.student_id = ?
  `;
  const params = [studentId];
  
  if (exam_group_id) {
    query += ' AND ea.exam_group_id = ?';
    params.push(exam_group_id);
  }
  
  query += ' ORDER BY ea.started_at DESC LIMIT 50';
  
  const attempts = db.prepare(query).all(...params);
  res.json(attempts);
});

// ============ GRADING ============

// Get exam results for teacher
router.get('/results', auth, (req, res) => {
  const { exam_group_id, class_id } = req.query;
  
  let query = `
    SELECT ea.*, u.first_name, u.last_name, u.email,
      eg.name as exam_name, eg.total_marks, eg.passing_marks, eg.exam_type
    FROM exam_attempts ea
    JOIN users u ON ea.student_id = u.id
    JOIN exam_groups eg ON ea.exam_group_id = eg.id
    LEFT JOIN enrollments e ON ea.student_id = e.student_id
    WHERE ea.status IN ('submitted', 'graded')
  `;
  const params = [];
  
  if (exam_group_id) {
    query += ' AND ea.exam_group_id = ?';
    params.push(exam_group_id);
  }
  if (class_id) {
    query += ' AND e.class_id = ?';
    params.push(class_id);
  }
  
  query += ' ORDER BY ea.percentage DESC';
  
  const results = db.prepare(query).all(...params);
  res.json(results);
});

// ============ STATS ============

// Get exam statistics
router.get('/stats', auth, (req, res) => {
  const { exam_group_id } = req.query;
  
  let whereClause = '';
  const params = [];
  
  if (exam_group_id) {
    whereClause = 'WHERE exam_group_id = ?';
    params.push(exam_group_id);
  }
  
  const stats = db.prepare(`
    SELECT 
      COUNT(*) as total_attempts,
      SUM(CASE WHEN status = 'submitted' OR status = 'graded' THEN 1 ELSE 0 END) as completed_attempts,
      AVG(percentage) as avg_percentage,
      MAX(percentage) as highest_percentage,
      MIN(percentage) as lowest_percentage,
      SUM(CASE WHEN percentage >= 50 THEN 1 ELSE 0 END) as passed,
      SUM(CASE WHEN percentage < 50 THEN 1 ELSE 0 END) as failed
    FROM exam_attempts
    ${whereClause}
  `).get(...params);
  
  // Question stats
  const questionStats = db.prepare(`
    SELECT 
      difficulty,
      COUNT(*) as total,
      AVG(marks) as avg_marks
    FROM question_banks
    WHERE exam_group_id = ? AND is_deleted = 0
    GROUP BY difficulty
  `).all(...params);
  
  res.json({ ...stats, questionStats });
});

module.exports = router;