const admin = require("firebase-admin");
const db = admin.firestore();
const logger = require("firebase-functions/logger");
const auth = require("../utils/auth");
const helpers = require("../utils/helpers");

// Créer un utilisateur
exports.createUser = async (req, res) => {
  try {
    const decodedToken = await auth.authenticateUser(req);
    const isAdminUser = await auth.isAdmin(decodedToken.uid);

    if (!isAdminUser) {
      res.status(403).json({error: "Forbidden: Admin access required"});
      return;
    }

    const userData = req.body.data;
    const userId = userData.uid;

    if (!userId) {
      res.status(400).json({error: "User ID is required"});
      return;
    }

    await db.collection("users").doc(userId).set(userData);

    res.status(201).json({id: userId, message: "User created successfully"});
  } catch (error) {
    logger.error("Error creating user:", error);
    res.status(500).json({error: error.message});
  }
};

// Créer un utilisateur avec invitation par email
exports.createUserWithInvite = async (req, res) => {
  try {
    const decodedToken = await auth.authenticateUser(req);
    const isAdminUser = await auth.isAdmin(decodedToken.uid);

    if (!isAdminUser) {
      res.status(403).json({error: "Forbidden: Admin access required"});
      return;
    }

    const {email, firstName, lastName, phoneNumber, roleId} = req.body.data;

    if (!email || !firstName || !lastName || !roleId) {
      res.status(400).json({error: "email, firstName, lastName, and roleId are required"});
      return;
    }

    const tempPassword = Math.random().toString(36).slice(-12) + "Aa1!";

    let userRecord;
    try {
      userRecord = await admin.auth().createUser({
        email: email,
        password: tempPassword,
        emailVerified: false,
        displayName: `${firstName} ${lastName}`,
      });
    } catch (authError) {
      logger.error("Error creating user in Auth:", authError);
      res.status(500).json({error: `Failed to create user in Auth: ${authError.message}`});
      return;
    }

    try {
      await db.collection("users").doc(userRecord.uid).set({
        firstName: firstName,
        lastName: lastName,
        email: email,
        phoneNumber: phoneNumber || "",
        profilePhotoUrl: "",
        role: db.collection("roles").doc(roleId),
        createdAt: admin.firestore.FieldValue.serverTimestamp(),
        createdBy: decodedToken.uid,
      });
    } catch (firestoreError) {
      logger.error("Error creating user in Firestore:", firestoreError);
      try {
        await admin.auth().deleteUser(userRecord.uid);
      } catch (cleanupError) {
        logger.error("Error cleaning up Auth user:", cleanupError);
      }
      res.status(500).json({error: `Failed to create user in Firestore: ${firestoreError.message}`});
      return;
    }

    try {
      const axios = require("axios");
      const firebaseApiKey = "AIzaSyARQL4P-t5l-cNjQNP9cMokQrLJ8BorF0U";

      await axios.post(
          `https://identitytoolkit.googleapis.com/v1/accounts:sendOobCode?key=${firebaseApiKey}`,
          {
            requestType: "PASSWORD_RESET",
            email: email,
          },
      );
      logger.info(`Password reset email sent to ${email}`);
    } catch (emailError) {
      logger.warn(`Could not send password reset email to ${email}: ${emailError.message}`);
    }

    logger.info(`User ${userRecord.uid} created by ${decodedToken.uid}`);
    res.status(201).json({
      id: userRecord.uid,
      message: "User created successfully. Password reset email sent.",
    });
  } catch (error) {
    logger.error("Error in createUserWithInvite:", error);
    res.status(500).json({error: error.message});
  }
};

// Mettre à jour un utilisateur
exports.updateUser = async (req, res) => {
  try {
    const decodedToken = await auth.authenticateUser(req);
    const {userId, data} = req.body.data;

    if (!userId) {
      res.status(400).json({error: "User ID is required"});
      return;
    }

    // Un utilisateur ne peut modifier que son propre compte, sauf s'il est admin
    const isAdminUser = await auth.isAdmin(decodedToken.uid);
    if (decodedToken.uid !== userId && !isAdminUser) {
      res.status(403).json({error: "Forbidden: Cannot update other user accounts"});
      return;
    }

    // Empêcher les non-admins de modifier le rôle
    if (!isAdminUser && data.role) {
      delete data.role;
    }

    // Si le rôle est fourni et est un string, le convertir en DocumentReference
    if (data.role && typeof data.role === "string") {
      data.role = db.collection("roles").doc(data.role);
    }

    await db.collection("users").doc(userId).update(data);

    res.status(200).json({message: "User updated successfully"});
  } catch (error) {
    logger.error("Error updating user:", error);
    res.status(500).json({error: error.message});
  }
};

// Supprimer un utilisateur
exports.deleteUser = async (req, res) => {
  try {
    const decodedToken = await auth.authenticateUser(req);
    const isAdminUser = await auth.isAdmin(decodedToken.uid);

    if (!isAdminUser) {
      res.status(403).json({error: "Forbidden: Admin access required"});
      return;
    }

    const {userId} = req.body.data;

    if (!userId) {
      res.status(400).json({error: "User ID is required"});
      return;
    }

    if (decodedToken.uid === userId) {
      res.status(400).json({error: "Cannot delete your own account"});
      return;
    }

    await db.collection("users").doc(userId).delete();

    try {
      await admin.auth().deleteUser(userId);
    } catch (authError) {
      logger.warn(`Could not delete user from Auth: ${authError.message}`);
    }

    res.status(200).json({message: "User deleted successfully"});
  } catch (error) {
    logger.error("Error deleting user:", error);
    res.status(500).json({error: error.message});
  }
};

// Récupérer tous les utilisateurs (selon permissions)
exports.getUsers = async (req, res) => {
  try {
    const decodedToken = await auth.authenticateUser(req);

    const canViewAll = await auth.hasPermission(decodedToken.uid, "view_all_users");

    if (!canViewAll) {
      const userDoc = await db.collection("users").doc(decodedToken.uid).get();

      if (!userDoc.exists) {
        res.status(404).json({error: "User not found"});
        return;
      }

      let userData = userDoc.data();
      userData = helpers.serializeTimestamps(userData);
      userData = helpers.serializeReferences(userData);

      res.status(200).json({
        users: [{
          id: userDoc.id,
          ...userData,
        }],
      });
      return;
    }

    const snapshot = await db.collection("users").get();
    const users = snapshot.docs.map((doc) => {
      let data = doc.data();
      data = helpers.serializeTimestamps(data);
      data = helpers.serializeReferences(data);
      return {
        id: doc.id,
        ...data,
      };
    });

    res.status(200).json({users});
  } catch (error) {
    logger.error("Error fetching users:", error);
    res.status(500).json({error: error.message});
  }
};

// Récupère un utilisateur spécifique
exports.getUser = async (req, res) => {
  try {
    const decodedToken = await auth.authenticateUser(req);

    const {userId} = req.body.data || req.body || {};
    if (!userId) {
      res.status(400).json({error: "userId is required"});
      return;
    }

    const userDoc = await db.collection("users").doc(userId).get();
    if (!userDoc.exists) {
      res.status(404).json({error: "User not found"});
      return;
    }

    const user = userDoc.data();

    const userData = {
      id: userDoc.id,
      uid: user.uid || userDoc.id,
      email: user.email || "",
      firstName: user.firstName || "",
      lastName: user.lastName || "",
      phoneNumber: user.phoneNumber || "",
      profilePhotoUrl: user.profilePhotoUrl || "",
    };

    if (user.role) {
      const roleDoc = await user.role.get();
      if (roleDoc.exists) {
        userData.role = {
          id: roleDoc.id,
          ...roleDoc.data(),
        };
      }
    }

    res.status(200).json({user: userData});
  } catch (error) {
    logger.error("Error fetching user:", error);
    res.status(500).json({error: error.message});
  }
};

// Récupère l'utilisateur actuellement authentifié avec son rôle
exports.getCurrentUser = async (req, res) => {
  try {
    const decodedToken = await auth.authenticateUser(req);
    const userId = decodedToken.uid;

    const userDoc = await db.collection("users").doc(userId).get();
    if (!userDoc.exists) {
      res.status(404).json({error: "User not found"});
      return;
    }

    const userData = userDoc.data();

    let roleData = null;
    if (userData.role) {
      const roleDoc = await userData.role.get();
      if (roleDoc.exists) {
        roleData = {id: roleDoc.id, ...roleDoc.data()};
      }
    }

    res.status(200).json({
      user: {
        uid: userId,
        ...helpers.serializeTimestamps(userData),
        role: roleData,
      },
    });
  } catch (error) {
    logger.error("Error getting current user:", error);
    res.status(500).json({error: error.message});
  }
};

// Récupère tous les rôles
exports.getRoles = async (req, res) => {
  try {
    await auth.authenticateUser(req);

    const snapshot = await db.collection("roles").get();
    const roles = snapshot.docs.map((doc) => ({
      id: doc.id,
      ...helpers.serializeTimestamps(doc.data()),
    }));

    res.status(200).json({roles});
  } catch (error) {
    logger.error("Error fetching roles:", error);
    res.status(500).json({error: error.message});
  }
};
