"use strict";
const { Router } = require("express");
const { query } = require("../db");
const { getSession } = require("../auth");
const router = Router();

function readerKey(role, userId, displayName) {
  if (role === "student" && userId != null) return `student:${userId}`;
  if (role === "teacher") return `teacher:${displayName}`;
  return `${role}:0`;
}

async function enrichMessages(rows, readSet) {
  if (!rows.length) return [];
  const classIds = [...new Set(rows.map(r => r.target_class_id).filter(Boolean))];
  const studentIds = [...new Set(rows.map(r => r.target_student_id).filter(Boolean))];
  const classes = classIds.length ? await query(`SELECT id, name FROM classes WHERE id IN (${classIds.map(() => "?").join(",")})`, classIds) : [];
  const students = studentIds.length ? await query(`SELECT id, first_name, last_name FROM students WHERE id IN (${studentIds.map(() => "?").join(",")})`, studentIds) : [];
  const cMap = new Map(classes.map(c => [c.id, c.name]));
  const sMap = new Map(students.map(s => [s.id, `${s.first_name} ${s.last_name}`]));

  const ids = rows.map(r => r.id);
  const readCounts = ids.length
    ? await query(`SELECT message_id, COUNT(*) AS cnt FROM message_reads WHERE message_id IN (${ids.map(() => "?").join(",")}) GROUP BY message_id`, ids)
    : [];
  const readCountMap = new Map(readCounts.map(r => [r.message_id, r.cnt]));
  const [[{ totalStudents }]] = [await query("SELECT COUNT(*) AS totalStudents FROM students")];

  return rows.map(r => ({
    id: r.id,
    senderRole: r.sender_role,
    senderName: r.sender_name,
    audience: r.audience,
    targetClassId: r.target_class_id,
    targetStudentId: r.target_student_id,
    targetClassName: r.target_class_id != null ? cMap.get(r.target_class_id) ?? null : null,
    targetStudentName: r.target_student_id != null ? sMap.get(r.target_student_id) ?? null : null,
    subject: r.subject,
    body: r.body,
    createdAt: r.created_at ? new Date(r.created_at).toISOString() : null,
    isRead: readSet.has(r.id),
    recipientCount: r.audience === "all" || r.audience === "students" ? totalStudents : 1,
    readCount: readCountMap.get(r.id) || 0,
  }));
}

async function inboxRows(role, userId, classId) {
  if (role === "student") {
    const conds = ["audience = 'all'", "audience = 'students'"];
    const params = [];
    if (classId != null) { conds.push("(audience = 'class' AND target_class_id = ?)"); params.push(classId); }
    if (userId != null) { conds.push("(audience = 'student' AND target_student_id = ?)"); params.push(userId); }
    return await query(`SELECT * FROM messages WHERE ${conds.join(" OR ")} ORDER BY created_at DESC`, params);
  }
  if (role === "teacher") {
    return await query("SELECT * FROM messages WHERE audience IN ('all','teachers') ORDER BY created_at DESC");
  }
  return await query("SELECT * FROM messages ORDER BY created_at DESC");
}

router.get("/messages", async (req, res) => {
  const session = getSession(req);
  if (!session || session.role === "guest") return res.status(401).json({ error: "Login required" });
  const scope = req.query.scope || "inbox";

  let rows;
  if (scope === "sent") {
    rows = await query("SELECT * FROM messages WHERE sender_name = ? ORDER BY created_at DESC", [session.displayName]);
  } else {
    let classId = null;
    if (session.role === "student" && session.userId) {
      const [s] = await query("SELECT class_id FROM students WHERE id = ?", [session.userId]);
      classId = s?.class_id ?? null;
    }
    rows = await inboxRows(session.role, session.userId, classId);
  }

  const key = readerKey(session.role, session.userId, session.displayName);
  const reads = rows.length
    ? await query(`SELECT message_id FROM message_reads WHERE message_id IN (${rows.map(() => "?").join(",")}) AND reader_role = ? AND reader_key = ?`, [...rows.map(r => r.id), session.role, key])
    : [];
  const readSet = new Set(reads.map(r => r.message_id));
  res.json(await enrichMessages(rows, readSet));
});

router.post("/messages", async (req, res) => {
  const session = getSession(req);
  if (!session || !["admin", "teacher", "developer"].includes(session.role)) {
    return res.status(403).json({ error: "Only staff can send messages" });
  }
  const { audience, subject, body, targetClassId, targetStudentId } = req.body || {};
  if (!audience || !subject || !body) return res.status(400).json({ error: "audience, subject, body required" });
  if (audience === "class" && targetClassId == null) return res.status(400).json({ error: "targetClassId required" });
  if (audience === "student" && targetStudentId == null) return res.status(400).json({ error: "targetStudentId required" });
  await query("INSERT INTO messages (sender_role, sender_name, audience, subject, body, target_class_id, target_student_id) VALUES (?, ?, ?, ?, ?, ?, ?)",
    [session.role, session.displayName, audience, subject, body, targetClassId ?? null, targetStudentId ?? null]);
  const [row] = await query("SELECT * FROM messages WHERE id = LAST_INSERT_ID()");
  await query("INSERT INTO activity_log (type, message) VALUES (?, ?)", ["message", `${session.displayName} sent: ${subject}`]);
  const [enriched] = await enrichMessages([row], new Set());
  res.status(201).json(enriched);
});

router.post("/messages/:id/read", async (req, res) => {
  const session = getSession(req);
  if (!session || session.role === "guest") return res.status(401).json({ error: "Login required" });
  const id = parseInt(req.params.id);
  if (!id) return res.status(400).json({ error: "Invalid id" });
  const key = readerKey(session.role, session.userId, session.displayName);
  await query("INSERT IGNORE INTO message_reads (message_id, reader_role, reader_key) VALUES (?, ?, ?)", [id, session.role, key]);
  res.status(204).end();
});

router.delete("/messages/:id", async (req, res) => {
  const session = getSession(req);
  if (!session) return res.status(401).json({ error: "Login required" });
  const id = parseInt(req.params.id);
  const [row] = await query("SELECT * FROM messages WHERE id = ?", [id]);
  if (!row) return res.status(404).json({ error: "Not found" });
  if (session.role !== "admin" && row.sender_name !== session.displayName) {
    return res.status(403).json({ error: "Forbidden" });
  }
  await query("DELETE FROM message_reads WHERE message_id = ?", [id]);
  await query("DELETE FROM messages WHERE id = ?", [id]);
  res.status(204).end();
});

router.get("/messages/unread-count", async (req, res) => {
  const session = getSession(req);
  if (!session || session.role === "guest") return res.json({ count: 0 });
  let classId = null;
  if (session.role === "student" && session.userId) {
    const [s] = await query("SELECT class_id FROM students WHERE id = ?", [session.userId]);
    classId = s?.class_id ?? null;
  }
  const rows = await inboxRows(session.role, session.userId, classId);
  if (!rows.length) return res.json({ count: 0 });
  const key = readerKey(session.role, session.userId, session.displayName);
  const reads = await query(`SELECT message_id FROM message_reads WHERE message_id IN (${rows.map(() => "?").join(",")}) AND reader_role = ? AND reader_key = ?`,
    [...rows.map(r => r.id), session.role, key]);
  const readSet = new Set(reads.map(r => r.message_id));
  res.json({ count: rows.filter(r => !readSet.has(r.id)).length });
});

module.exports = router;
