/**
 * Utilitaires d'authentification et d'autorisation
 */
const admin = require("firebase-admin");
const logger = require("firebase-functions/logger");

/**
 * Vérifie le token Firebase et retourne l'utilisateur
 */
async function authenticateUser(req) {
  if (!req.headers.authorization || !req.headers.authorization.startsWith("Bearer ")) {
    throw new Error("Unauthorized: No token provided");
  }

  const idToken = req.headers.authorization.split("Bearer ")[1];
  try {
    const decodedToken = await admin.auth().verifyIdToken(idToken);
    return decodedToken;
  } catch (e) {
    logger.error("Error verifying Firebase ID token:", e);
    throw new Error("Unauthorized: Invalid token");
  }
}

/**
 * Récupère les données utilisateur depuis Firestore
 */
async function getUserData(uid) {
  const userDoc = await admin.firestore().collection("users").doc(uid).get();
  if (!userDoc.exists) {
    return null;
  }
  return {uid, ...userDoc.data()};
}

/**
 * Récupère les permissions d'un rôle
 */
async function getRolePermissions(roleRef) {
  if (!roleRef) return [];

  let roleId;
  if (typeof roleRef === "string") {
    roleId = roleRef;
  } else if (roleRef.id) {
    roleId = roleRef.id;
  } else {
    return [];
  }

  const roleDoc = await admin.firestore().collection("roles").doc(roleId).get();
  if (!roleDoc.exists) return [];

  return roleDoc.data().permissions || [];
}

/**
 * Vérifie si l'utilisateur a une permission spécifique
 */
async function hasPermission(uid, requiredPermission) {
  const userData = await getUserData(uid);
  if (!userData) return false;

  const permissions = await getRolePermissions(userData.role);
  return permissions.includes(requiredPermission);
}

/**
 * Vérifie si l'utilisateur est admin
 */
async function isAdmin(uid) {
  const userData = await getUserData(uid);
  if (!userData) return false;

  let roleId;
  const roleField = userData.role;
  if (typeof roleField === "string") {
    roleId = roleField;
  } else if (roleField && roleField.id) {
    roleId = roleField.id;
  } else {
    return false;
  }

  return roleId === "ADMIN";
}

/**
 * Vérifie si l'utilisateur est assigné à un événement
 */
async function isAssignedToEvent(uid, eventId) {
  const eventDoc = await admin.firestore().collection("events").doc(eventId).get();
  if (!eventDoc.exists) return false;

  const eventData = eventDoc.data();
  const workforce = eventData.workforce || [];

  // workforce contient des références DocumentReference
  return workforce.some((ref) => {
    if (typeof ref === "string") return ref === uid;
    if (ref && ref.id) return ref.id === uid;
    return false;
  });
}

/**
 * Middleware d'authentification pour les Cloud Functions HTTP
 */
async function authMiddleware(req, res, next) {
  try {
    const decodedToken = await authenticateUser(req);
    req.user = decodedToken;
    req.uid = decodedToken.uid;
    next();
  } catch (error) {
    res.status(401).json({error: error.message});
  }
}

/**
 * Middleware de vérification de permission
 */
function requirePermission(permission) {
  return async (req, res, next) => {
    try {
      const hasAccess = await hasPermission(req.uid, permission);
      if (!hasAccess) {
        res.status(403).json({error: `Forbidden: Requires permission '${permission}'`});
        return;
      }
      next();
    } catch (error) {
      res.status(403).json({error: error.message});
    }
  };
}

/**
 * Middleware admin uniquement
 */
async function requireAdmin(req, res, next) {
  try {
    const adminAccess = await isAdmin(req.uid);
    if (!adminAccess) {
      res.status(403).json({error: "Forbidden: Admin access required"});
      return;
    }
    next();
  } catch (error) {
    res.status(403).json({error: error.message});
  }
}

module.exports = {
  authenticateUser,
  getUserData,
  getRolePermissions,
  hasPermission,
  isAdmin,
  isAssignedToEvent,
  authMiddleware,
  requirePermission,
  requireAdmin,
};

