import express from "express";
import multer from "multer";
import path from "path";
import fs from "fs";

import { requireAuth, requireRole } from "../../middleware/auth.js";
import { validate } from "../../shared/validate.js";
import { Announcement } from "./announcement.model.js";
import { createAnnouncementSchema } from "./announcements.schemas.js";
import { User } from "../users/user.model.js";
import { createAndSendNotifications } from "../notifications/notification.service.js";

export const announcementsRouter = express.Router();
announcementsRouter.use(requireAuth);

const uploadsDir = path.join(process.cwd(), "uploads");
fs.mkdirSync(uploadsDir, { recursive: true });

const upload = multer({
  storage: multer.diskStorage({
    destination: (_req, _file, cb) => cb(null, uploadsDir),
    filename: (_req, file, cb) => {
      const original = String(file.originalname || "file");
      const ext = path.extname(original).slice(0, 10);
      const base = path
        .basename(original, ext)
        .replace(/[^a-zA-Z0-9_-]+/g, "-")
        .slice(0, 40);
      const unique = `${Date.now()}-${Math.random().toString(16).slice(2, 10)}`;
      cb(null, `ann-${base || "file"}-${unique}${ext}`);
    },
  }),
  limits: { fileSize: 15 * 1024 * 1024 },
});

announcementsRouter.get("/", async (req, res, next) => {
  try {
    const query = {
      $or: [{ audienceRoles: { $size: 0 } }, { audienceRoles: req.user.role }],
    };

    const items = await Announcement.find(query)
      .sort({ createdAt: -1 })
      .limit(50)
      .lean();
    res.json({ items });
  } catch (err) {
    next(err);
  }
});

announcementsRouter.post(
  "/",
  requireRole("admin"),
  validate(createAnnouncementSchema),
  async (req, res, next) => {
    try {
      const { title, body, audienceRoles, attachments } = req.validated.body;

      const doc = await Announcement.create({
        title,
        body,
        createdBy: req.user._id,
        audienceRoles: audienceRoles || [],
        attachments: attachments || [],
      });

      // Notify relevant users (in-app + push if registered)
      try {
        const roles = Array.isArray(audienceRoles) ? audienceRoles : [];
        const userQuery = {
          status: "active",
          ...(roles.length > 0 ? { role: { $in: roles } } : {}),
        };
        const users = await User.find(userQuery, "_id").lean();
        await createAndSendNotifications({
          userIds: users.map((u) => u._id),
          type: "announcement",
          title: `Announcement: ${title}`,
          body: typeof body === "string" ? body.slice(0, 140) : undefined,
          data: { kind: "announcement", announcementId: doc._id },
          createdBy: req.user._id,
        });
      } catch {
        // ignore notification failures
      }

      res.status(201).json({ announcement: doc });
    } catch (err) {
      next(err);
    }
  }
);

announcementsRouter.post(
  "/uploads",
  requireRole("admin"),
  upload.single("file"),
  async (req, res, next) => {
    try {
      if (!req.file) return res.status(400).json({ error: "No file uploaded" });
      const mimeType = req.file.mimetype;
      const isImage =
        typeof mimeType === "string" && mimeType.startsWith("image/");
      res.json({
        url: `/uploads/${req.file.filename}`,
        filename: req.file.originalname,
        mimeType,
        type: isImage ? "image" : "file",
        size: req.file.size,
      });
    } catch (err) {
      next(err);
    }
  }
);
