const { Router } = require("express");
const prisma = require("../prisma");
const { requireAuth } = require("../middleware/auth");
const { requireUserManager } = require("../lib/rbac");
const { isSystemPermissionName } = require("../lib/permissionCatalog");

const router = Router();

function formatPermission(p) {
  return {
    id: p.id,
    name: p.name,
    label: p.label || p.name,
    description: p.description || "",
    category: p.category || "General",
    sortOrder: p.sortOrder ?? 0,
    isSystem: Boolean(p.isSystem),
    roleCount: p._count?.roles,
    createdAt: p.createdAt,
    updatedAt: p.updatedAt,
  };
}

function prismaConflict(err, res) {
  if (err.code === "P2002") return res.status(409).json({ error: "Permission already exists" });
  return null;
}

router.get("/", requireAuth, requireUserManager, async (req, res, next) => {
  try {
    const page = Math.max(1, parseInt(req.query.page) || 1);
    const limit = Math.min(200, Math.max(1, parseInt(req.query.limit) || 50));
    const skip = (page - 1) * limit;
    const search = (req.query.search || "").trim();

    const where = {};
    if (search) {
      where.OR = [
        { name: { contains: search, mode: "insensitive" } },
        { label: { contains: search, mode: "insensitive" } },
        { description: { contains: search, mode: "insensitive" } },
        { category: { contains: search, mode: "insensitive" } },
      ];
    }

    const [total, rows] = await Promise.all([
      prisma.permission.count({ where }),
      prisma.permission.findMany({
        where,
        orderBy: [{ sortOrder: "asc" }, { label: "asc" }],
        skip,
        take: limit,
        include: { _count: { select: { roles: true } } },
      }),
    ]);

    return res.json({
      data: rows.map(formatPermission),
      pagination: { page, limit, total, totalPages: Math.ceil(total / limit) },
    });
  } catch (err) {
    return next(err);
  }
});

router.get("/:id", requireAuth, requireUserManager, async (req, res, next) => {
  try {
    const row = await prisma.permission.findUnique({
      where: { id: req.params.id },
      include: { roles: { include: { role: true } } },
    });
    if (!row) return res.status(404).json({ error: "Not found" });
    return res.json({
      ...formatPermission({ ...row, _count: { roles: row.roles.length } }),
      roles: row.roles.map((r) => r.role),
    });
  } catch (err) {
    return next(err);
  }
});

/** System permissions are defined by the app — admins assign them to roles only. */
router.post("/", requireAuth, requireUserManager, async (req, res, next) => {
  try {
    return res.status(403).json({
      error:
        "Permissions are built into SMARTPOS and cannot be created manually. Assign existing permissions to roles instead.",
    });
  } catch (err) {
    return next(err);
  }
});

router.patch("/:id", requireAuth, requireUserManager, async (req, res, next) => {
  try {
    const { id } = req.params;
    const existing = await prisma.permission.findUnique({ where: { id } });
    if (!existing) return res.status(404).json({ error: "Not found" });

    if (existing.isSystem || isSystemPermissionName(existing.name)) {
      return res.status(403).json({
        error: "System permissions cannot be edited. They are maintained by the application.",
      });
    }

    const body = req.body || {};
    const data = {};
    if (body.name !== undefined) {
      const name = String(body.name || "").trim();
      if (!name) return res.status(400).json({ error: "Name cannot be empty" });
      data.name = name;
    }
    if (body.label !== undefined) data.label = String(body.label || "").trim();
    if (body.description !== undefined) data.description = String(body.description || "").trim();

    const row = await prisma.permission.update({ where: { id }, data });
    return res.json(formatPermission({ ...row, _count: { roles: 0 } }));
  } catch (err) {
    const r = prismaConflict(err, res);
    if (r) return r;
    return next(err);
  }
});

router.delete("/:id", requireAuth, requireUserManager, async (req, res, next) => {
  try {
    const { id } = req.params;
    const row = await prisma.permission.findUnique({ where: { id } });
    if (!row) return res.status(404).json({ error: "Not found" });

    if (row.isSystem || isSystemPermissionName(row.name)) {
      return res.status(403).json({
        error: "System permissions cannot be deleted. They are required by SMARTPOS features.",
      });
    }

    await prisma.permission.delete({ where: { id } });
    return res.json({ ok: true });
  } catch (err) {
    return next(err);
  }
});

module.exports = router;
