/**
 * Assignments Controller
 * Assignment/homework management
 */

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

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

const getDb = () => {
  if (!db) {
    db = new Database(dbPath);
    db.pragma('foreign_keys = ON');
  }
  return db;
};

// 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 {
    const jwt = require('jsonwebtoken');
    const JWT_SECRET = process.env.JWT_SECRET || 'africa-alert-secret-key-2024';
    req.user = jwt.verify(token, JWT_SECRET);
    next();
  } catch (err) {
    res.status(401).json({ error: 'Invalid token' });
  }
};

// Admin or teacher only
const adminOrTeacher = (req, res, next) => {
  if (req.user.role !== 'admin' && req.user.role !== 'teacher') {
    return res.status(403).json({ error: 'Admin or Teacher access required' });
  }
  next();
};

// Admin-only middleware
const adminOnly = (req, res, next) => {
  if (req.user.role !== 'admin') {
    return res.status(403).json({ error: 'Admin access required' });
  }
  next();
};

// Create assignments table if not exists
const ensureTable = () => {
  getDb().exec(`
    CREATE TABLE IF NOT EXISTS assignments (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      uid TEXT UNIQUE,
      subject_id INTEGER REFERENCES subjects(id),
      title TEXT NOT NULL,
      description TEXT,
      due_date DATE,
      total_marks REAL DEFAULT 100,
      created_by INTEGER REFERENCES users(id),
      assigned_to_class INTEGER REFERENCES classes(id),
      status TEXT DEFAULT 'active' CHECK(status IN ('active', 'closed', 'draft')),
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      last_synced_at DATETIME,
      sync_status TEXT DEFAULT 'pending',
      is_deleted INTEGER DEFAULT 0
    );
    
    CREATE TABLE IF NOT EXISTS assignment_submissions (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      uid TEXT UNIQUE,
      assignment_id INTEGER NOT NULL REFERENCES assignments(id),
      student_id INTEGER NOT NULL REFERENCES users(id),
      submission_text TEXT,
      file_path TEXT,
      submitted_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      status TEXT DEFAULT 'pending' CHECK(status IN ('pending', 'submitted', 'graded', 'returned')),
      marks_obtained REAL,
      feedback TEXT,
      graded_by INTEGER REFERENCES users(id),
      graded_at DATETIME,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      last_synced_at DATETIME,
      sync_status TEXT DEFAULT 'pending',
      is_deleted INTEGER DEFAULT 0
    );
  `);
};

// ============ ASSIGNMENTS CRUD ============

// List assignments
router.get('/', auth, (req, res) => {
  try {
    ensureTable();
    const { subject_id, class_id, status, due_before, due_after } = req.query;
    
    let query = `
      SELECT a.*, 
        s.name as subject_name,
        c.name as class_name,
        u.first_name || ' ' || u.last_name as created_by_name,
        (SELECT COUNT(*) FROM assignment_submissions WHERE assignment_id = a.id AND is_deleted = 0) as submission_count,
        (SELECT COUNT(*) FROM assignment_submissions WHERE assignment_id = a.id AND status = 'graded' AND is_deleted = 0) as graded_count
      FROM assignments a
      LEFT JOIN subjects s ON a.subject_id = s.id
      LEFT JOIN classes c ON a.assigned_to_class = c.id
      LEFT JOIN users u ON a.created_by = u.id
      WHERE a.is_deleted = 0
    `;
    const params = [];
    
    if (subject_id) {
      query += ' AND a.subject_id = ?';
      params.push(subject_id);
    }
    if (class_id) {
      query += ' AND a.assigned_to_class = ?';
      params.push(class_id);
    }
    if (status) {
      query += ' AND a.status = ?';
      params.push(status);
    }
    if (due_before) {
      query += ' AND a.due_date <= ?';
      params.push(due_before);
    }
    if (due_after) {
      query += ' AND a.due_date >= ?';
      params.push(due_after);
    }
    
    // Filter by teacher
    if (req.user.role === 'teacher') {
      query += ' AND (a.created_by = ? OR s.teacher_id = ?)';
      params.push(req.user.id, req.user.id);
    }
    
    query += ' ORDER BY a.due_date DESC, a.created_at DESC';
    
    const assignments = getDb().prepare(query).all(...params);
    res.json(assignments);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Get single assignment
router.get('/:id', auth, (req, res) => {
  try {
    ensureTable();
    const assignment = getDb().prepare(`
      SELECT a.*, 
        s.name as subject_name,
        c.name as class_name,
        u.first_name || ' ' || u.last_name as created_by_name
      FROM assignments a
      LEFT JOIN subjects s ON a.subject_id = s.id
      LEFT JOIN classes c ON a.assigned_to_class = c.id
      LEFT JOIN users u ON a.created_by = u.id
      WHERE a.id = ? AND a.is_deleted = 0
    `).get(req.params.id);
    
    if (!assignment) {
      return res.status(404).json({ error: 'Assignment not found' });
    }
    
    // Get submissions
    const submissions = getDb().prepare(`
      SELECT s.*, u.first_name || ' ' || u.last_name as student_name, u.email as student_email
      FROM assignment_submissions s
      JOIN users u ON s.student_id = u.id
      WHERE s.assignment_id = ? AND s.is_deleted = 0
      ORDER BY s.submitted_at DESC
    `).all(req.params.id);
    
    res.json({ ...assignment, submissions });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Create assignment
router.post('/', auth, adminOrTeacher, (req, res) => {
  try {
    ensureTable();
    const { subject_id, title, description, due_date, total_marks, assigned_to_class } = req.body;
    
    if (!title || !subject_id) {
      return res.status(400).json({ error: 'Title and subject are required' });
    }
    
    const uid = uuidv4();
    
    const result = getDb().prepare(`
      INSERT INTO assignments (uid, subject_id, title, description, due_date, total_marks, assigned_to_class, created_by)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    `).run(uid, subject_id, title, description, due_date, total_marks || 100, assigned_to_class, req.user.id);
    
    const assignment = getDb().prepare(`
      SELECT a.*, s.name as subject_name, c.name as class_name
      FROM assignments a
      LEFT JOIN subjects s ON a.subject_id = s.id
      LEFT JOIN classes c ON a.assigned_to_class = c.id
      WHERE a.id = ?
    `).get(result.lastInsertRowid);
    
    res.status(201).json(assignment);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Update assignment
router.put('/:id', auth, adminOrTeacher, (req, res) => {
  try {
    ensureTable();
    const { title, description, due_date, total_marks, status } = req.body;
    
    // Only creator can update
    const assignment = getDb().prepare('SELECT created_by FROM assignments WHERE id = ?').get(req.params.id);
    if (!assignment) {
      return res.status(404).json({ error: 'Assignment not found' });
    }
    if (req.user.role !== 'admin' && assignment.created_by !== req.user.id) {
      return res.status(403).json({ error: 'Only the creator can update this assignment' });
    }
    
    getDb().prepare(`
      UPDATE assignments SET
        title = COALESCE(?, title),
        description = COALESCE(?, description),
        due_date = COALESCE(?, due_date),
        total_marks = COALESCE(?, total_marks),
        status = COALESCE(?, status),
        updated_at = CURRENT_TIMESTAMP,
        sync_status = 'pending'
      WHERE id = ? AND is_deleted = 0
    `).run(title, description, due_date, total_marks, status, req.params.id);
    
    const updated = getDb().prepare(`
      SELECT a.*, s.name as subject_name, c.name as class_name
      FROM assignments a
      LEFT JOIN subjects s ON a.subject_id = s.id
      LEFT JOIN classes c ON a.assigned_to_class = c.id
      WHERE a.id = ?
    `).get(req.params.id);
    
    res.json(updated);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Delete assignment
router.delete('/:id', auth, adminOrTeacher, (req, res) => {
  try {
    ensureTable();
    const assignment = getDb().prepare('SELECT created_by FROM assignments WHERE id = ?').get(req.params.id);
    if (!assignment) {
      return res.status(404).json({ error: 'Assignment not found' });
    }
    if (req.user.role !== 'admin' && assignment.created_by !== req.user.id) {
      return res.status(403).json({ error: 'Only the creator can delete this assignment' });
    }
    
    getDb().prepare(`
      UPDATE assignments SET is_deleted = 1, updated_at = CURRENT_TIMESTAMP, sync_status = 'pending'
      WHERE id = ?
    `).run(req.params.id);
    
    res.json({ success: true, message: 'Assignment deleted' });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// ============ SUBMISSIONS ============

// Submit assignment (student)
router.post('/:id/submit', auth, (req, res) => {
  try {
    ensureTable();
    const { submission_text, file_path } = req.body;
    
    // Check if already submitted
    const existing = getDb().prepare('SELECT id FROM assignment_submissions WHERE assignment_id = ? AND student_id = ? AND is_deleted = 0').get(req.params.id, req.user.id);
    
    if (existing) {
      // Update existing submission
      getDb().prepare(`
        UPDATE assignment_submissions SET
          submission_text = COALESCE(?, submission_text),
          file_path = COALESCE(?, file_path),
          submitted_at = CURRENT_TIMESTAMP,
          status = 'submitted',
          updated_at = CURRENT_TIMESTAMP,
          sync_status = 'pending'
        WHERE id = ?
      `).run(submission_text, file_path, existing.id);
      
      const updated = getDb().prepare('SELECT * FROM assignment_submissions WHERE id = ?').get(existing.id);
      return res.json(updated);
    }
    
    const uid = uuidv4();
    const result = getDb().prepare(`
      INSERT INTO assignment_submissions (uid, assignment_id, student_id, submission_text, file_path, status)
      VALUES (?, ?, ?, ?, ?, 'submitted')
    `).run(uid, req.params.id, req.user.id, submission_text, file_path);
    
    const submission = getDb().prepare('SELECT * FROM assignment_submissions WHERE id = ?').get(result.lastInsertRowid);
    res.status(201).json(submission);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Grade submission (teacher)
router.put('/:id/submissions/:submissionId/grade', auth, adminOrTeacher, (req, res) => {
  try {
    ensureTable();
    const { marks_obtained, feedback } = req.body;
    
    if (marks_obtained === undefined) {
      return res.status(400).json({ error: 'Marks obtained is required' });
    }
    
    getDb().prepare(`
      UPDATE assignment_submissions SET
        marks_obtained = ?,
        feedback = ?,
        status = 'graded',
        graded_by = ?,
        graded_at = CURRENT_TIMESTAMP,
        updated_at = CURRENT_TIMESTAMP,
        sync_status = 'pending'
      WHERE id = ? AND is_deleted = 0
    `).run(marks_obtained, feedback, req.user.id, req.params.submissionId);
    
    const submission = getDb().prepare(`
      SELECT s.*, u.first_name || ' ' || u.last_name as student_name
      FROM assignment_submissions s
      JOIN users u ON s.student_id = u.id
      WHERE s.id = ?
    `).get(req.params.submissionId);
    
    res.json(submission);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Get my submissions (student)
router.get('/my/submissions', auth, (req, res) => {
  try {
    ensureTable();
    const { assignment_id } = req.query;
    
    let query = `
      SELECT s.*, a.title as assignment_title, a.total_marks, s.marks_obtained
      FROM assignment_submissions s
      JOIN assignments a ON s.assignment_id = a.id
      WHERE s.student_id = ? AND s.is_deleted = 0
    `;
    const params = [req.user.id];
    
    if (assignment_id) {
      query += ' AND s.assignment_id = ?';
      params.push(assignment_id);
    }
    
    query += ' ORDER BY s.submitted_at DESC';
    
    const submissions = getDb().prepare(query).all(...params);
    res.json(submissions);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

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

router.get('/stats/overview', auth, adminOrTeacher, (req, res) => {
  try {
    ensureTable();
    let whereClause = '';
    const params = [];
    
    if (req.user.role === 'teacher') {
      whereClause = ' AND (a.created_by = ? OR s.teacher_id = ?)';
      params.push(req.user.id, req.user.id);
    }
    
    const stats = getDb().prepare(`
      SELECT 
        COUNT(*) as total_assignments,
        SUM(CASE WHEN a.status = 'active' THEN 1 ELSE 0 END) as active,
        SUM(CASE WHEN a.status = 'closed' THEN 1 ELSE 0 END) as closed,
        SUM((SELECT COUNT(*) FROM assignment_submissions WHERE assignment_id = a.id)) as total_submissions,
        SUM((SELECT COUNT(*) FROM assignment_submissions WHERE assignment_id = a.id AND status = 'graded')) as total_graded
      FROM assignments a
      LEFT JOIN subjects s ON a.subject_id = s.id
      WHERE a.is_deleted = 0 ${whereClause}
    `).get(...params);
    
    res.json(stats);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

module.exports = router;