const overlayAccessProviders = [];

const OVERLAY_CAPABILITIES = Object.freeze({
  MANAGE: "manage",
  VIEW_SECRETS: "view_secrets",
  CONTROL_SCENE: "control_scene",
  MANAGE_OBS: "manage_obs"
});

function registerOverlayAccessProvider(provider) {
  if (!provider || typeof provider.allows !== "function") {
    throw new Error("Overlay access providers must expose allows(context).");
  }
  overlayAccessProviders.push(provider);
  return () => {
    const index = overlayAccessProviders.indexOf(provider);
    if (index >= 0) overlayAccessProviders.splice(index, 1);
  };
}

function canAccessOverlay(user, overlayId, capability = OVERLAY_CAPABILITIES.MANAGE) {
  if (!user) return false;
  if (user.isAdmin) return true;

  // Deliberately deny by default. A future moderator-assignment provider can be
  // registered here without weakening secret access or changing route checks.
  if (capability === OVERLAY_CAPABILITIES.VIEW_SECRETS || capability === OVERLAY_CAPABILITIES.MANAGE_OBS) {
    return false;
  }
  return overlayAccessProviders.some((provider) => {
    try {
      return provider.allows({ user, overlayId, capability }) === true;
    } catch {
      return false;
    }
  });
}

function requireOverlayCapability(capability, getOverlayId = (req) => req.params.id) {
  return (req, res, next) => {
    const overlayId = getOverlayId(req);
    if (!canAccessOverlay(req.session?.user, overlayId, capability)) {
      return res.status(403).render("error", {
        title: "Access denied",
        message: "You do not have access to that overlay."
      });
    }
    next();
  };
}

module.exports = {
  OVERLAY_CAPABILITIES,
  canAccessOverlay,
  registerOverlayAccessProvider,
  requireOverlayCapability
};
