/**
 * Teacher Controller
 * Handles syllabuses, schemes of work, focus points, and lesson plans
 */

const express = require('express');
const router = express.Router();
const path = require('path');
const Database = require('better-sqlite3');
const { v4: uuidv4 } = require('uuid');
const { normalizeHttpUrl } = require('../utils/validateUrl');

const dbPath = process.env.DB_PATH || path.join(__dirname, '../../data/school.db');
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 {
    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 teacherOnly = (req, res, next) => {
  const allowedRoles = ['teacher', 'school_admin', 'systems_admin', 'principal'];
  if (!allowedRoles.includes(req.user.role)) {
    return res.status(403).json({ error: 'Teacher, Principal or Admin access required' });
  }
  next();
};

// Helper to check if user is a department head and return their department ID
const getDepartmentHeadId = (userId) => {
  const dept = db.prepare('SELECT id FROM departments WHERE head_teacher_id = ? AND is_deleted = 0').get(userId);
  return dept ? dept.id : null;
};

// ============ SYLLABUSES ============

/**
 * @openapi
 * /api/teacher/syllabuses:
 *   get:
 *     summary: List teacher syllabuses
 *     description: |
 *       Returns syllabuses scoped to the caller. Privileged users
 *       (`school_admin`, `systems_admin`, `principal`) see every
 *       active syllabus; department heads see syllabuses for
 *       subjects in their department; other teachers see only
 *       syllabuses for their own subjects.
 *     tags:
 *       - Teacher
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: Syllabus list
 *         content:
 *           application/json:
 *             schema:
 *               type: array
 *               items: { type: object }
 *       401: { description: Unauthorized }
 *       500: { description: Server error }
 */
router.get('/syllabuses', auth, (req, res) => {
  const isPrivileged = ['school_admin', 'systems_admin', 'principal'].includes(req.user.role);
  const deptId = getDepartmentHeadId(req.user.id);

  let query, params;

  if (isPrivileged) {
    query = `
      SELECT s.*, sub.name as subject_name
      FROM syllabuses s
      JOIN subjects_new sub ON s.subject_id = sub.id
      WHERE s.is_deleted = 0
    `;
    params = [];
  } else if (deptId) {
    query = `
      SELECT s.*, sub.name as subject_name
      FROM syllabuses s
      JOIN subjects_new sub ON s.subject_id = sub.id
      WHERE sub.department_id = ? AND s.is_deleted = 0
    `;
    params = [deptId];
  } else {
    query = `
      SELECT s.*, sub.name as subject_name
      FROM syllabuses s
      JOIN subjects_new sub ON s.subject_id = sub.id
      WHERE sub.teacher_id = ? AND s.is_deleted = 0
    `;
    params = [req.user.id];
  }

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

/**
 * @openapi
 * /api/teacher/syllabuses:
 *   post:
 *     summary: Create teacher syllabus
 *     description: |
 *       Creates a syllabus record attached to a subject. Restricted
 *       to teachers and admin/principal roles.
 *     tags:
 *       - Teacher
 *     security:
 *       - bearerAuth: []
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required:
 *               - subject_id
 *               - title
 *             properties:
 *               subject_id: { type: integer }
 *               title: { type: string }
 *               description: { type: string }
 *               file_path: { type: string }
 *               version: { type: string }
 *     responses:
 *       200:
 *         description: Created syllabus id and uid
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 id: { type: integer }
 *                 uid: { type: string }
 *       401: { description: Unauthorized }
 *       403: { description: Teacher, Principal or Admin only }
 */
// DEPRECATED - New syllabus uploads use the attachments controller at /api/attachments with parent_kind='subject'
router.post('/syllabuses', auth, teacherOnly, (req, res) => {
  const { subject_id, title, description, file_path, version } = req.body;
  const uid = uuidv4();
  const result = db.prepare(`
    INSERT INTO syllabuses (uid, subject_id, title, description, file_path, version, created_by, sync_status)
    VALUES (?, ?, ?, ?, ?, ?, ?, 'pending')
  `).run(uid, subject_id, title, description, file_path, version, req.user.id);
  res.json({ id: result.lastInsertRowid, uid });
});

// ============ SCHEMES OF WORK ============

/**
 * @openapi
 * /api/teacher/schemes:
 *   get:
 *     summary: List schemes of work
 *     description: |
 *       Returns active schemes of work scoped to the caller.
 *       Privileged users (`school_admin`, `systems_admin`,
 *       `principal`) see every scheme; department heads see schemes
 *       for subjects in their department plus their own; other
 *       teachers see only the schemes they authored.
 *     tags:
 *       - Teacher
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: Scheme list
 *         content:
 *           application/json:
 *             schema:
 *               type: array
 *               items: { type: object }
 *       401: { description: Unauthorized }
 */
router.get('/schemes', auth, (req, res) => {
  const isPrivileged = ['school_admin', 'systems_admin', 'principal'].includes(req.user.role);
  const deptId = getDepartmentHeadId(req.user.id);
  
  let query, params;
  
  if (isPrivileged) {
    query = 'SELECT sow.*, sub.name as subject_name, u.first_name, u.last_name FROM schemes_of_work sow JOIN subjects_new sub ON sow.subject_id = sub.id JOIN users u ON sow.teacher_id = u.id WHERE sow.is_deleted = 0';
    params = [];
  } else if (deptId) {
    // Department head: see all schemes in their department
    query = `
      SELECT sow.*, sub.name as subject_name, u.first_name, u.last_name 
      FROM schemes_of_work sow 
      JOIN subjects_new sub ON sow.subject_id = sub.id 
      JOIN users u ON sow.teacher_id = u.id 
      WHERE (sub.department_id = ? OR sow.teacher_id = ?) AND sow.is_deleted = 0
    `;
    params = [deptId, req.user.id];
  } else {
    // Normal teacher: see only own schemes
    query = 'SELECT sow.*, sub.name as subject_name FROM schemes_of_work sow JOIN subjects_new sub ON sow.subject_id = sub.id WHERE sow.teacher_id = ? AND sow.is_deleted = 0';
    params = [req.user.id];
  }
  
  const schemes = db.prepare(query).all(...params);
  res.json(schemes);
});

/**
 * @openapi
 * /api/teacher/schemes:
 *   post:
 *     summary: Create scheme of work
 *     description: |
 *       Creates a scheme of work for a subject in the given term and
 *       academic year. The authenticated user becomes the
 *       `teacher_id`. Restricted to teachers and admin/principal
 *       roles.
 *     tags:
 *       - Teacher
 *     security:
 *       - bearerAuth: []
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required:
 *               - subject_id
 *             properties:
 *               subject_id: { type: integer }
 *               term: { type: string }
 *               academic_year: { type: string }
 *               content: { type: string }
 *     responses:
 *       200:
 *         description: Created scheme id and uid
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 id: { type: integer }
 *                 uid: { type: string }
 *       401: { description: Unauthorized }
 *       403: { description: Teacher, Principal or Admin only }
 */
router.post('/schemes', auth, teacherOnly, (req, res) => {
  const { subject_id, term, academic_year, content } = req.body;
  const uid = uuidv4();
  const result = db.prepare(`
    INSERT INTO schemes_of_work (uid, subject_id, teacher_id, term, academic_year, content, sync_status)
    VALUES (?, ?, ?, ?, ?, ?, 'pending')
  `).run(uid, subject_id, req.user.id, term, academic_year, content);
  res.json({ id: result.lastInsertRowid, uid });
});

// ============ FOCUS POINTS ============

/**
 * @openapi
 * /api/teacher/focus-points:
 *   get:
 *     summary: List focus points
 *     description: |
 *       Returns active focus points joined with their parent scheme
 *       (term, academic year) and subject. Optionally filtered by
 *       `scheme_id`.
 *     tags:
 *       - Teacher
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: query
 *         name: scheme_id
 *         schema: { type: integer }
 *     responses:
 *       200:
 *         description: Focus point list
 *         content:
 *           application/json:
 *             schema:
 *               type: array
 *               items: { type: object }
 *       401: { description: Unauthorized }
 *       500: { description: Server error }
 */
router.get('/focus-points', auth, (req, res) => {
  const { scheme_id } = req.query;
  let query = `
    SELECT fp.*, sow.term as scheme_term, sow.academic_year as scheme_academic_year, sub.name as subject_name
    FROM focus_points fp
    JOIN schemes_of_work sow ON fp.scheme_id = sow.id
    JOIN subjects_new sub ON sow.subject_id = sub.id
    WHERE fp.is_deleted = 0
  `;
  const params = [];
  if (scheme_id) {
    query += ' AND fp.scheme_id = ?';
    params.push(scheme_id);
  }
  try {
    const points = db.prepare(query).all(...params);
    res.json(points);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

/**
 * @openapi
 * /api/teacher/focus-points:
 *   post:
 *     summary: Create focus point
 *     description: |
 *       Adds a focus point to a scheme. Restricted to teachers and
 *       admin/principal roles; non-privileged callers may only add
 *       focus points to schemes they themselves own.
 *     tags:
 *       - Teacher
 *     security:
 *       - bearerAuth: []
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required:
 *               - scheme_id
 *               - topic
 *             properties:
 *               scheme_id: { type: integer }
 *               topic: { type: string }
 *               objectives: { type: string }
 *               key_concepts: { type: string }
 *               resources_needed: { type: string }
 *     responses:
 *       200:
 *         description: Created focus point id and uid
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 id: { type: integer }
 *                 uid: { type: string }
 *       401: { description: Unauthorized }
 *       403: { description: Teacher, Principal or Admin only }
 *       404: { description: Scheme not found }
 *       500: { description: Server error }
 */
router.post('/focus-points', auth, teacherOnly, (req, res) => {
  const { scheme_id, topic, objectives, key_concepts, resources_needed } = req.body;
  try {
    const scheme = db.prepare('SELECT teacher_id FROM schemes_of_work WHERE id = ? AND is_deleted = 0').get(scheme_id);
    if (!scheme) return res.status(404).json({ error: 'Scheme not found' });
    const isPrivileged = ['school_admin', 'systems_admin', 'principal'].includes(req.user.role);
    if (!isPrivileged && scheme.teacher_id !== req.user.id) {
      return res.status(403).json({ error: 'You can only add focus points to your own schemes' });
    }
    const uid = uuidv4();
    const result = db.prepare(`
      INSERT INTO focus_points (uid, scheme_id, topic, objectives, key_concepts, resources_needed, sync_status)
      VALUES (?, ?, ?, ?, ?, ?, 'pending')
    `).run(uid, scheme_id, topic, objectives, key_concepts, resources_needed);
    res.json({ id: result.lastInsertRowid, uid });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// ============ LESSON PLANS ============

/**
 * @openapi
 * /api/teacher/lesson-plans:
 *   get:
 *     summary: List lesson plans
 *     description: |
 *       Returns active lesson plans joined with subject, teacher,
 *       scheme term/year, and focus-point topic. Scoped to the
 *       caller: privileged users see every plan, department heads
 *       see plans in their department plus their own, other
 *       teachers see only plans they authored.
 *     tags:
 *       - Teacher
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: Lesson plan list
 *         content:
 *           application/json:
 *             schema:
 *               type: array
 *               items: { type: object }
 *       401: { description: Unauthorized }
 *       500: { description: Server error }
 */
router.get('/lesson-plans', auth, (req, res) => {
  const isPrivileged = ['school_admin', 'systems_admin', 'principal'].includes(req.user.role);
  const deptId = getDepartmentHeadId(req.user.id);
  
  let query, params;

  if (isPrivileged) {
    query = `
      SELECT lp.*, sub.name as subject_name, u.first_name, u.last_name, sow.term as scheme_term, sow.academic_year as scheme_academic_year, fp.topic as focus_point_topic
      FROM lesson_plans lp 
      JOIN subjects_new sub ON lp.subject_id = sub.id 
      JOIN users u ON lp.teacher_id = u.id 
      LEFT JOIN schemes_of_work sow ON lp.scheme_id = sow.id
      LEFT JOIN focus_points fp ON lp.focus_point_id = fp.id
      WHERE lp.is_deleted = 0
    `;
    params = [];
  } else if (deptId) {
    query = `
      SELECT lp.*, sub.name as subject_name, u.first_name, u.last_name, sow.term as scheme_term, sow.academic_year as scheme_academic_year, fp.topic as focus_point_topic
      FROM lesson_plans lp 
      JOIN subjects_new sub ON lp.subject_id = sub.id 
      JOIN users u ON lp.teacher_id = u.id 
      LEFT JOIN schemes_of_work sow ON lp.scheme_id = sow.id
      LEFT JOIN focus_points fp ON lp.focus_point_id = fp.id
      WHERE (sub.department_id = ? OR lp.teacher_id = ?) AND lp.is_deleted = 0
    `;
    params = [deptId, req.user.id];
  } else {
    query = `
      SELECT lp.*, sub.name as subject_name, sow.term as scheme_term, sow.academic_year as scheme_academic_year, fp.topic as focus_point_topic
      FROM lesson_plans lp 
      JOIN subjects_new sub ON lp.subject_id = sub.id 
      LEFT JOIN schemes_of_work sow ON lp.scheme_id = sow.id
      LEFT JOIN focus_points fp ON lp.focus_point_id = fp.id
      WHERE lp.teacher_id = ? AND lp.is_deleted = 0
    `;
    params = [req.user.id];
  }
  
  try {
    const plans = db.prepare(query).all(...params);
    res.json(plans);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

/**
 * @openapi
 * /api/teacher/lesson-plans:
 *   post:
 *     summary: Create lesson plan
 *     description: |
 *       Creates a lesson plan for a subject, optionally linked to a
 *       scheme and/or focus point. Restricted to teachers and
 *       admin/principal roles; non-privileged callers may only link
 *       to schemes and focus points they themselves own.
 *     tags:
 *       - Teacher
 *     security:
 *       - bearerAuth: []
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required:
 *               - subject_id
 *               - date
 *               - topic
 *             properties:
 *               subject_id: { type: integer }
 *               scheme_id: { type: integer }
 *               focus_point_id: { type: integer }
 *               date: { type: string, format: date }
 *               topic: { type: string }
 *               objectives: { type: string }
 *               introduction: { type: string }
 *               development: { type: string }
 *               conclusion: { type: string }
 *               assessment_method: { type: string }
 *               homework: { type: string }
 *               reflections: { type: string }
 *               meet_url:
 *                 type: string
 *                 format: uri
 *                 nullable: true
 *                 description: |
 *                   Optional Google Meet link to the live lesson. Must be
 *                   a valid http(s) URL; otherwise the server returns 400.
 *                 example: "https://meet.google.com/abc-defg-hij"
 *               classroom_url:
 *                 type: string
 *                 format: uri
 *                 nullable: true
 *                 description: |
 *                   Optional Google Classroom link to the
 *                   assignment/coursework for this lesson. Must be a valid
 *                   http(s) URL; otherwise the server returns 400.
 *                 example: "https://classroom.google.com/c/NDAwMDAxMjM"
 *     responses:
 *       200:
 *         description: Created lesson plan id and uid
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 id: { type: integer }
 *                 uid: { type: string }
 *       401: { description: Unauthorized }
 *       403: { description: Teacher, Principal or Admin only }
 *       404: { description: Scheme or focus point not found }
 *       500: { description: Server error }
 */
router.post('/lesson-plans', auth, teacherOnly, (req, res) => {
  const { subject_id, scheme_id, focus_point_id, date, topic, objectives, introduction, development, conclusion, assessment_method, homework, reflections, meet_url, classroom_url } = req.body;
  try {
    const isPrivileged = ['school_admin', 'systems_admin', 'principal'].includes(req.user.role);
    if (scheme_id) {
      const scheme = db.prepare('SELECT teacher_id FROM schemes_of_work WHERE id = ? AND is_deleted = 0').get(scheme_id);
      if (!scheme) return res.status(404).json({ error: 'Scheme not found' });
      if (!isPrivileged && scheme.teacher_id !== req.user.id) {
        return res.status(403).json({ error: 'You can only add lesson plans to your own schemes' });
      }
    }
    if (focus_point_id) {
      const fp = db.prepare('SELECT scheme_id FROM focus_points WHERE id = ? AND is_deleted = 0').get(focus_point_id);
      if (!fp) return res.status(404).json({ error: 'Focus point not found' });
      const fpScheme = db.prepare('SELECT teacher_id FROM schemes_of_work WHERE id = ? AND is_deleted = 0').get(fp.scheme_id);
      if (!fpScheme) return res.status(404).json({ error: 'Scheme for focus point not found' });
      if (!isPrivileged && fpScheme.teacher_id !== req.user.id) {
        return res.status(403).json({ error: 'You can only add lesson plans to focus points in your own schemes' });
      }
    }
    // P1-UX-3 — Meet / Classroom links. Empty / null means "no link set";
    // a non-empty value must parse as http(s) via validateUrl.normalizeHttpUrl.
    // We reject with 400 if a link was supplied but is not http(s) so a
    // teacher pasting the wrong shape is told immediately rather than
    // silently persisted as junk.
    let normalizedMeetUrl = null;
    if (meet_url !== undefined && meet_url !== null && String(meet_url).trim() !== '') {
      normalizedMeetUrl = normalizeHttpUrl(meet_url);
      if (normalizedMeetUrl === null) {
        return res.status(400).json({ error: 'meet_url must be a valid http(s) URL' });
      }
    }
    let normalizedClassroomUrl = null;
    if (classroom_url !== undefined && classroom_url !== null && String(classroom_url).trim() !== '') {
      normalizedClassroomUrl = normalizeHttpUrl(classroom_url);
      if (normalizedClassroomUrl === null) {
        return res.status(400).json({ error: 'classroom_url must be a valid http(s) URL' });
      }
    }
    const uid = uuidv4();
    const result = db.prepare(`
      INSERT INTO lesson_plans (uid, teacher_id, subject_id, scheme_id, focus_point_id, date, topic, objectives, introduction, development, conclusion, assessment_method, homework, reflections, meet_url, classroom_url, sync_status)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending')
    `).run(
      uid, req.user.id, subject_id, scheme_id || null, focus_point_id || null,
      date, topic, objectives, introduction, development, conclusion,
      assessment_method, homework, reflections, normalizedMeetUrl, normalizedClassroomUrl
    );
    res.json({ id: result.lastInsertRowid, uid });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

module.exports = router;
