const User = require("../models/userModel");
const catchAsync = require("../utils/catchAsync");
const AppError = require("../utils/appError");

const {
  uploadUserPhoto,
  handleBase64Image,
  deleteOldPhoto,
} = require("../storage/middlewareStorage/uploadUserPhoto");

// Helper to filter allowed fields
const filterObj = (obj, ...allowedFields) => {
  const newObj = {};
  Object.keys(obj).forEach((el) => {
    if (allowedFields.includes(el)) newObj[el] = obj[el];
  });
  return newObj;
};

// Export middlewares
exports.uploadUserPhoto = uploadUserPhoto;
exports.handleBase64Image = handleBase64Image;

// --- READ: Get All Users ---
exports.getAllUsers = catchAsync(async (req, res, next) => {
  const filter = {};
  if (req.query.role) filter.role = req.query.role;

  const users = await User.find(filter);

  res.status(200).json({
    status: "success",
    results: users.length,
    data: { users },
  });
});

// --- READ: Get Single User ---
exports.getUser = catchAsync(async (req, res, next) => {
  const user = await User.findById(req.params.id);
  if (!user) {
    return next(new AppError("No user found with that ID", 404));
  }
  res.status(200).json({
    status: "success",
    data: { user },
  });
});

// --- CREATE: Add Admin ---
exports.createAdmin = catchAsync(async (req, res, next) => {
  if (req.user.role !== "super-admin") {
    return next(new AppError("Only Super Admins can create new Admins.", 403));
  }

  // Get filename from either multer or base64 handler
  const photoName = req.file ? req.file.filename : req.body.photo;

  const newAdmin = await User.create({
    name: req.body.name,
    email: req.body.email,
    password: req.body.password,
    passwordConfirm: req.body.passwordConfirm,
    role: "admin",
    gender: req.body.gender,
    photo: photoName,
  });

  newAdmin.password = undefined;

  res.status(201).json({
    status: "success",
    data: { user: newAdmin },
  });
});

// --- UPDATE: Edit User (Admin) ---
exports.updateUser = catchAsync(async (req, res, next) => {
  // ✅ REMOVED the check blocking password updates

  // 1. Filter allowed fields (Add 'password' and 'passwordConfirm' to allowed list)
  // We need to manually handle password hashing if it's included,
  // because findByIdAndUpdate DOES NOT trigger pre-save hooks (hashing).

  const user = await User.findById(req.params.id);
  if (!user) {
    return next(new AppError("No user found with that ID", 404));
  }

  // 2. Handle Password Update Manually (if provided)
  if (req.body.password) {
    user.password = req.body.password;
    user.passwordConfirm = req.body.passwordConfirm || req.body.password;
    await user.save(); // This triggers the hashing hook
  }

  // 3. Handle Other Fields
  const filteredBody = filterObj(
    req.body,
    "name",
    "email",
    "gender",
    "bio",
    "role"
  ); // Added role just in case

  // Handle Photo
  if (req.file || req.body.photo) {
    const photoName = req.file ? req.file.filename : req.body.photo;
    filteredBody.photo = photoName;
    if (user.photo && !user.photo.startsWith("default")) {
      // Safety check
      await deleteOldPhoto(user.photo);
    }
  }

  // Update non-password fields
  const updatedUser = await User.findByIdAndUpdate(
    req.params.id,
    filteredBody,
    {
      new: true,
      runValidators: true,
    }
  );

  res.status(200).json({
    status: "success",
    data: { user: updatedUser },
  });
});

// --- DELETE: Delete User ---
exports.deleteUser = catchAsync(async (req, res, next) => {
  const userToDelete = await User.findById(req.params.id);

  if (!userToDelete) {
    return next(new AppError("No user found with that ID", 404));
  }

  if (userToDelete.role === "super-admin") {
    return next(new AppError("You cannot delete a Super Admin.", 403));
  }

  if (userToDelete.photo) {
    await deleteOldPhoto(userToDelete.photo);
  }

  await User.findByIdAndDelete(req.params.id);

  res.status(204).json({
    status: "success",
    data: null,
  });
});

// --- GET ME ---
exports.getMe = (req, res, next) => {
  req.params.id = req.user.id;
  next();
};

// --- UPDATE ME (Student/User Profile) ---
// Allows students to update Name, Email, Gender, and Photo
exports.updateMe = catchAsync(async (req, res, next) => {
  // 1) Create error if user POSTs password data
  if (req.body.password || req.body.passwordConfirm) {
    return next(
      new AppError(
        "This route is not for password updates. Please use /updateMyPassword.",
        400
      )
    );
  }

  // 2) Filter out unwanted field names
  const filteredBody = filterObj(req.body, "name", "email", "gender", "photo");

  // 3) Handle Custom 'delete' flag for photo
  if (req.body.photo === "delete") {
    // a. Delete the old custom photo if it exists
    if (req.user.photo && !req.user.photo.startsWith("default")) {
      await deleteOldPhoto(req.user.photo);
    }
    // b. Reset to default based on gender
    filteredBody.photo =
      req.user.gender === "female" ? "defaultFemale.png" : "defaultMale.png";
  }
  // 4) Handle normal photo upload
  else if (req.file) {
    filteredBody.photo = req.file.filename;
    // Delete old photo if replacing
    if (req.user.photo && !req.user.photo.startsWith("default")) {
      await deleteOldPhoto(req.user.photo);
    }
  }

  // 5) Update user document
  const updatedUser = await User.findByIdAndUpdate(req.user.id, filteredBody, {
    new: true,
    runValidators: true,
  });

  res.status(200).json({
    status: "success",
    data: {
      user: updatedUser,
    },
  });
});
exports.getStudentCount = catchAsync(async (req, res, next) => {
  const count = await User.countDocuments({ role: "student" });

  res.status(200).json({
    status: "success",
    data: {
      count,
    },
  });
});
