/**
 * Homework Controller
 * Homework and submission management
 */

const express = require('express');
const router = express.Router();
const { v4: uuidv4 } = require('uuid');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const Database = require('better-sqlite3');

const uploadDir = path.join(__dirname, '../../uploads');
if (!fs.existsSync(uploadDir)) {
  fs.mkdirSync(uploadDir, { recursive: true });
}

// Multer storage for student homework uploads
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, uploadDir);
  },
  filename: function (req, file, cb) {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    cb(null, uniqueSuffix + path.extname(file.originalname));
  }
});

const upload = multer({
  storage: storage,
  limits: { fileSize: 20 * 1024 * 1024 } // 20MB limit
});

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

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 { jwtSecret: JWT_SECRET } = require('../config');
    req.user = jwt.verify(token, JWT_SECRET);
    next();
  } catch (err) {
    res.status(401).json({ error: 'Invalid token' });
  }
};

const adminOrTeacher = (req, res, next) => {
  if (!['systems_admin', 'school_admin', 'principal', 'teacher'].includes(req.user.role)) {
    return res.status(403).json({ error: 'Admin or Teacher access required' });
  }
  next();
};

// GET /api/homework - List homework
router.get('/', auth, (req, res) => {
  try {
    const { subject_id, class_id, status } = req.query;

    let query = `
      SELECT h.*,
        sub.name as subject_name,
        c.name as class_name,
        (SELECT COUNT(*) FROM homework_submissions WHERE homework_id = h.id AND is_deleted = 0) as submission_count,
        (SELECT COUNT(*) FROM homework_submissions WHERE homework_id = h.id AND status = 'graded' AND is_deleted = 0) as graded_count
      FROM homework h
      LEFT JOIN subjects_new sub ON h.subject_id = sub.id
      LEFT JOIN classes c ON h.class_id = c.id
      WHERE h.is_deleted = 0
    `;
    const params = [];

    if (subject_id) {
      query += ' AND h.subject_id = ?';
      params.push(subject_id);
    }
    if (class_id) {
      query += ' AND h.class_id = ?';
      params.push(class_id);
    }
    if (status) {
      query += ' AND h.status = ?';
      params.push(status);
    }

    if (req.user.role === 'teacher') {
      query += ' AND (sub.teacher_id = ?)';
      params.push(req.user.id);
    } else if (req.user.role === 'student') {
      // Students only see published or closed homework for classes they are in
      query += ` AND h.status IN ('published', 'closed') AND h.class_id IN (
        SELECT class_id FROM enrollments WHERE student_id = ? AND is_deleted = 0 AND status = 'active'
      )`;
      params.push(req.user.id);
    } else if (req.user.role === 'parent') {
      // Parents see homework for their children's classes
      query += ` AND h.status IN ('published', 'closed') AND h.class_id IN (
        SELECT class_id FROM enrollments WHERE student_id IN (
          SELECT student_id FROM parent_students WHERE parent_id = ? AND is_deleted = 0
        ) AND is_deleted = 0 AND status = 'active'
      )`;
      params.push(req.user.id);
    }

    query += ' ORDER BY h.due_date DESC, h.created_at DESC';

    const homework = db.prepare(query).all(...params);
    res.json(homework);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// GET /api/homework/my/submissions - Get student's own submissions (registered before /:id)
router.get('/my/submissions', auth, (req, res) => {
  try {
    const { homework_id } = req.query;

    let query = `
      SELECT s.*, h.title as homework_title, h.max_score
      FROM homework_submissions s
      JOIN homework h ON s.homework_id = h.id
      WHERE s.student_id = ? AND s.is_deleted = 0
    `;
    const params = [req.user.id];

    if (homework_id) {
      query += ' AND s.homework_id = ?';
      params.push(homework_id);
    }

    query += ' ORDER BY s.submitted_at DESC';

    const submissions = db.prepare(query).all(...params);
    res.json(submissions);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// GET /api/homework/:id - Detail view
router.get('/:id', auth, (req, res) => {
  try {
    const hw = db.prepare(`
      SELECT h.*,
        sub.name as subject_name,
        c.name as class_name,
        (SELECT COUNT(*) FROM homework_submissions WHERE homework_id = h.id AND is_deleted = 0) as submission_count,
        (SELECT COUNT(*) FROM homework_submissions WHERE homework_id = h.id AND status = 'graded' AND is_deleted = 0) as graded_count
      FROM homework h
      LEFT JOIN subjects_new sub ON h.subject_id = sub.id
      LEFT JOIN classes c ON h.class_id = c.id
      WHERE h.id = ? AND h.is_deleted = 0
    `).get(req.params.id);

    if (!hw) {
      return res.status(404).json({ error: 'Homework not found' });
    }

    // Get submissions
    let submissions = [];
    if (['systems_admin', 'school_admin', 'principal', 'teacher'].includes(req.user.role)) {
      // Teachers/admins see all submissions
      submissions = db.prepare(`
        SELECT s.*, u.first_name || ' ' || u.last_name as student_name, u.email as student_email
        FROM homework_submissions s
        JOIN users u ON s.student_id = u.id
        WHERE s.homework_id = ? AND s.is_deleted = 0
        ORDER BY s.submitted_at DESC
      `).all(req.params.id);
    } else if (req.user.role === 'student') {
      // Students only see their own submission
      submissions = db.prepare(`
        SELECT s.*, u.first_name || ' ' || u.last_name as student_name, u.email as student_email
        FROM homework_submissions s
        JOIN users u ON s.student_id = u.id
        WHERE s.homework_id = ? AND s.student_id = ? AND s.is_deleted = 0
      `).all(req.params.id, req.user.id);
    } else if (req.user.role === 'parent') {
      // Parents see their children's submissions
      submissions = db.prepare(`
        SELECT s.*, u.first_name || ' ' || u.last_name as student_name, u.email as student_email
        FROM homework_submissions s
        JOIN users u ON s.student_id = u.id
        WHERE s.homework_id = ? AND s.is_deleted = 0 AND s.student_id IN (
          SELECT student_id FROM parent_students WHERE parent_id = ? AND is_deleted = 0
        )
      `).all(req.params.id, req.user.id);
    }

    // Join attachments for submissions
    if (submissions.length > 0) {
      const submissionIds = submissions.map((s) => s.id);
      const placeholders = submissionIds.map(() => '?').join(',');
      const attachmentRows = db.prepare(`
        SELECT * FROM attachments
        WHERE parent_kind = 'submission' AND parent_id IN (${placeholders}) AND is_deleted = 0
        ORDER BY uploaded_at DESC
      `).all(...submissionIds);

      // Join marked scripts
      const markedScriptRows = db.prepare(`
        SELECT * FROM attachments
        WHERE parent_kind = 'marked_script' AND parent_id IN (${placeholders}) AND is_deleted = 0
        ORDER BY uploaded_at DESC
      `).all(...submissionIds);

      const attachmentsByParent = new Map();
      for (const a of attachmentRows) {
        if (!attachmentsByParent.has(a.parent_id)) attachmentsByParent.set(a.parent_id, []);
        attachmentsByParent.get(a.parent_id).push(a);
      }

      const markedByParent = new Map();
      for (const a of markedScriptRows) {
        if (!markedByParent.has(a.parent_id)) markedByParent.set(a.parent_id, []);
        markedByParent.get(a.parent_id).push(a);
      }

      submissions.forEach((s) => {
        s.attachments = attachmentsByParent.get(s.id) || [];
        // If student/parent, only show marked_script if status is returned
        if (['student', 'parent'].includes(req.user.role) && s.status !== 'returned') {
          s.marked_scripts = [];
        } else {
          s.marked_scripts = markedByParent.get(s.id) || [];
        }
      });
    }

    res.json({ ...hw, submissions });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// POST /api/homework - Create homework
router.post('/', auth, adminOrTeacher, (req, res) => {
  try {
    const { subject_id, class_id, title, description, instructions, due_date, max_score, allow_late_submission } = req.body;

    if (!title || !subject_id) {
      return res.status(400).json({ error: 'Title and subject are required' });
    }

    const uid = uuidv4();
    const allowLate = allow_late_submission ? 1 : 0;

    const result = db.prepare(`
      INSERT INTO homework (uid, subject_id, class_id, title, description, instructions, due_date, max_score, allow_late_submission, status, is_published, created_by)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'draft', 0, ?)
    `).run(uid, subject_id, class_id || null, title, description || null, instructions || null, due_date || null, max_score || 100, allowLate, req.user.id);

    const hw = db.prepare(`
      SELECT h.*, sub.name as subject_name
      FROM homework h
      LEFT JOIN subjects_new sub ON h.subject_id = sub.id
      WHERE h.id = ?
    `).get(result.lastInsertRowid);

    res.status(201).json(hw);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// PUT /api/homework/:id - Update homework
router.put('/:id', auth, adminOrTeacher, (req, res) => {
  try {
    const { title, description, instructions, due_date, max_score, allow_late_submission, status } = req.body;

    const hw = db.prepare(`
      SELECT h.*, sub.teacher_id
      FROM homework h
      JOIN subjects_new sub ON h.subject_id = sub.id
      WHERE h.id = ? AND h.is_deleted = 0
    `).get(req.params.id);

    if (!hw) {
      return res.status(404).json({ error: 'Homework not found' });
    }

    const isPrivileged = ['systems_admin', 'school_admin', 'principal'].includes(req.user.role);
    if (!isPrivileged && hw.teacher_id !== req.user.id) {
      return res.status(403).json({ error: 'Only the course teacher can update this homework' });
    }

    const allowLate = allow_late_submission === undefined ? null : (allow_late_submission ? 1 : 0);
    const derivedIsPublished = status === undefined ? null : (status === 'published' ? 1 : 0);

    db.prepare(`
      UPDATE homework SET
        title = COALESCE(?, title),
        description = COALESCE(?, description),
        instructions = COALESCE(?, instructions),
        due_date = COALESCE(?, due_date),
        max_score = COALESCE(?, max_score),
        allow_late_submission = COALESCE(?, allow_late_submission),
        status = COALESCE(?, status),
        is_published = COALESCE(?, is_published),
        updated_at = CURRENT_TIMESTAMP,
        sync_status = 'pending'
      WHERE id = ?
    `).run(title, description, instructions, due_date, max_score, allowLate, status, derivedIsPublished, req.params.id);

    const updated = db.prepare(`
      SELECT h.*, sub.name as subject_name
      FROM homework h
      LEFT JOIN subjects_new sub ON h.subject_id = sub.id
      WHERE h.id = ?
    `).get(req.params.id);

    res.json(updated);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// DELETE /api/homework/:id - Soft delete
router.delete('/:id', auth, adminOrTeacher, (req, res) => {
  try {
    const hw = db.prepare(`
      SELECT h.*, sub.teacher_id
      FROM homework h
      JOIN subjects_new sub ON h.subject_id = sub.id
      WHERE h.id = ? AND h.is_deleted = 0
    `).get(req.params.id);

    if (!hw) {
      return res.status(404).json({ error: 'Homework not found' });
    }

    const isPrivileged = ['systems_admin', 'school_admin', 'principal'].includes(req.user.role);
    if (!isPrivileged && hw.teacher_id !== req.user.id) {
      return res.status(403).json({ error: 'Only the course teacher can delete this homework' });
    }

    db.prepare(`
      UPDATE homework SET is_deleted = 1, updated_at = CURRENT_TIMESTAMP, sync_status = 'pending'
      WHERE id = ?
    `).run(req.params.id);

    res.json({ success: true, message: 'Homework deleted' });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// POST /api/homework/:id/submit - Student submit
router.post('/:id/submit', auth, upload.single('file'), (req, res) => {
  try {
    const { content } = req.body;

    const hw = db.prepare('SELECT * FROM homework WHERE id = ? AND is_deleted = 0').get(req.params.id);
    if (!hw) {
      return res.status(404).json({ error: 'Homework not found' });
    }

    // Check if already submitted
    const existing = db.prepare('SELECT id FROM homework_submissions WHERE homework_id = ? AND student_id = ? AND is_deleted = 0').get(req.params.id, req.user.id);

    let submissionId;
    if (existing) {
      db.prepare(`
        UPDATE homework_submissions SET
          content = COALESCE(?, content),
          submitted_at = CURRENT_TIMESTAMP,
          status = 'submitted',
          updated_at = CURRENT_TIMESTAMP,
          sync_status = 'pending'
        WHERE id = ?
      `).run(content || null, existing.id);
      submissionId = existing.id;
    } else {
      const uid = uuidv4();
      const result = db.prepare(`
        INSERT INTO homework_submissions (uid, homework_id, student_id, content, status)
        VALUES (?, ?, ?, ?, 'submitted')
      `).run(uid, req.params.id, req.user.id, content || null);
      submissionId = result.lastInsertRowid;
    }

    // Write file attachment if uploaded
    if (req.file) {
      const attachmentUid = uuidv4();
      db.prepare(`
        INSERT INTO attachments (
          uid, parent_kind, parent_id, original_filename, stored_filename,
          mime_type, size_bytes, uploaded_by, sync_status
        ) VALUES (?, 'submission', ?, ?, ?, ?, ?, ?, 'pending')
      `).run(
        attachmentUid,
        submissionId,
        req.file.originalname,
        req.file.filename,
        req.file.mimetype,
        req.file.size,
        req.user.id
      );
    }

    const updatedSubmission = db.prepare('SELECT * FROM homework_submissions WHERE id = ?').get(submissionId);
    res.status(201).json(updatedSubmission);
  } catch (error) {
    if (req.file && req.file.path) {
      fs.unlink(req.file.path, () => {});
    }
    res.status(500).json({ error: error.message });
  }
});

// PUT/POST /api/homework/:id/submissions/:sid/grade - Grade submission
const gradeSubmissionHandler = (req, res) => {
  try {
    const grade = req.body.grade !== undefined ? req.body.grade : req.body.score;
    const { feedback } = req.body;

    if (grade === undefined) {
      return res.status(400).json({ error: 'Grade is required' });
    }

    db.prepare(`
      UPDATE homework_submissions SET
        grade = ?,
        feedback = ?,
        status = 'graded',
        graded_by = ?,
        graded_at = CURRENT_TIMESTAMP,
        updated_at = CURRENT_TIMESTAMP,
        sync_status = 'pending'
      WHERE id = ? AND homework_id = ? AND is_deleted = 0
    `).run(grade, feedback || null, req.user.id, req.params.sid, req.params.id);

    const submission = db.prepare(`
      SELECT s.*, u.first_name || ' ' || u.last_name as student_name
      FROM homework_submissions s
      JOIN users u ON s.student_id = u.id
      WHERE s.id = ?
    `).get(req.params.sid);

    res.json(submission);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};
router.put('/:id/submissions/:sid/grade', auth, adminOrTeacher, gradeSubmissionHandler);
router.post('/:id/submissions/:sid/grade', auth, adminOrTeacher, gradeSubmissionHandler);

// POST /api/homework/:id/submissions/:sid/return - Return submission (marked script)
router.post('/:id/submissions/:sid/return', auth, adminOrTeacher, (req, res) => {
  try {
    db.prepare(`
      UPDATE homework_submissions SET
        status = 'returned',
        updated_at = CURRENT_TIMESTAMP,
        sync_status = 'pending'
      WHERE id = ? AND homework_id = ? AND is_deleted = 0
    `).run(req.params.sid, req.params.id);

    const submission = db.prepare(`
      SELECT s.*, u.first_name || ' ' || u.last_name as student_name
      FROM homework_submissions s
      JOIN users u ON s.student_id = u.id
      WHERE s.id = ?
    `).get(req.params.sid);

    // PR 3 §13 follow-up — push marked_script:returned event so the
    // student dashboard + parent's Marked Scripts section update live.
    const wsHub = req.app.get('wsHub');
    if (wsHub && submission) {
      const markedRows = db.prepare(`
        SELECT * FROM attachments
        WHERE parent_kind = 'marked_script' AND parent_id = ? AND is_deleted = 0
        ORDER BY uploaded_at DESC
      `).all(submission.id);
      const payload = {
        type: 'marked_script:returned',
        data: {
          kind: 'homework',
          submission_id: submission.id,
          homework_id: submission.homework_id,
          student_id: submission.student_id,
          graded_at: submission.updated_at,
          marked_scripts: markedRows,
        },
      };
      wsHub.broadcastToUser(submission.student_id, payload);
      try {
        const rows = db.prepare(`
          SELECT parent_id FROM parent_students WHERE student_id = ? AND is_deleted = 0
        `).all(submission.student_id);
        for (const r of rows) wsHub.broadcastToUser(r.parent_id, payload);
      } catch (err) {
        console.warn('[homework] parent fan-out failed:', err.message);
      }
    }

    res.json(submission);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

module.exports = router;
