const User = require("../models/userModel");
const { errorResponse } = require("../utils/errorResponseHandler");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const { logUserAction } = require("../utils/userActionLogger");
require("../models/roleModel")
const Role = require("../models/roleModel");
const Task = require("../models/taskModel")
const mongoose = require("mongoose");
// const Otp = require("../models/otpModel");
// const User = require("../models/userModel");


// Helper to get IP address

// ------------------ REGISTER ------------------
// const registerUser = async (req, res) => {
//   try {
//     const { firstName, lastName, email, password, phone, orgId, gender } = req.body;
//     if (!firstName || !email || !password || !orgId) {
//       return errorResponse(res, "First name, email, password and organization ID are required", 400);
//     }

//     const existingUser = await User.findOne({ email });
//     if (existingUser) return errorResponse(res, "Email already in use", 400);

//     const hashedPassword = await bcrypt.hash(password, 10);
//     const newUser = new User({
//       firstName,
//       lastName,
//       email,
//       password: hashedPassword,
//       phone,
//       role: "user",
//       orgId,
//       gender: gender || "other",
//     });

//     const savedUser = await newUser.save();

//     // Generate token for the new user
//     const token = jwt.sign(
//       { userId: savedUser._id, role: savedUser.role },
//       process.env.JWT_SECRET,
//       { expiresIn: "30d" }
//     );

//     await logUserAction({
//       userId: savedUser._id,
//       action: "REGISTER",
//       model: "User",
//       details: { email, firstName, lastName },
//       req
//     });

//     return res.status(201).json({
//       success: true,
//       message: "User registered successfully",
//       data: { user: savedUser, token }, // include token
//     });
//   } catch (err) {
//     return errorResponse(res, "Failed to register user", 500, err);
//   }
// };

const registerUser = async (req, res) => {
  try {
    const {
      firstName,
      lastName,
      email,
      password,
      phone,
      orgId,
      gender,
      department,
      designation,
      employeeId,
      salary,
      workingDays = 30,
      // workingHours = 8,
      employeeType = "full-time",
      reportingManager,
      // status,
      address,
      role,
    } = req.body;

    if (department && !mongoose.Types.ObjectId.isValid(department)) {
      return errorResponse(res, "Invalid department", 400);
    }

    // if (designation && !mongoose.Types.ObjectId.isValid(designation)) {
    //   return errorResponse(res, "Invalid designation", 400);
    // }

    if (!firstName || !email || !password || !orgId) {
      return errorResponse(
        res,
        "First name, email, password and organization ID are required",
        400
      );
    }

    const existingUser = await User.findOne({ email });
    if (existingUser) {
      return errorResponse(res, "Email already in use", 400);
    }

    const hashedPassword = await bcrypt.hash(password, 10);

    // ✅ HANDLE IMAGE SAFELY



    // ✅ Parse address if sent as string
    let parsedAddress = {};
    if (address) {
      try {
        parsedAddress = typeof address === "string" ? JSON.parse(address) : address;
      } catch {
        parsedAddress = {};
      }
    }

    let parsedSpecializations = [];
    if (req.body.specializations) {
      try {
        parsedSpecializations =
          typeof req.body.specializations === "string"
            ? JSON.parse(req.body.specializations)
            : req.body.specializations;
      } catch {
        parsedSpecializations = [];
      }
    }

    const consultationFee = req.body.consultationFee
      ? Number(req.body.consultationFee)
      : null;

    const workingHours = {
      start: req.body.startTime || "09:30",
      end: req.body.endTime || "18:30",
    };


    // added by me
    // const userRole = await Role.findOne({ name: "user" });
    // if (!userRole) {
    //   return errorResponse(res, "Default role not found", 500);
    // }
    // validations
    // if (!salary || Number(salary) <= 0) {
    //   return errorResponse(res, "Salary must be a positive number", 400);
    // }

    if (workingDays < 1 || workingDays > 31) {
      return errorResponse(res, "Invalid working days", 400);
    }

    if (workingHours < 1 || workingHours > 24) {
      return errorResponse(res, "Invalid working hours", 400);
    }

    let roleDoc;

    if (role) {

      roleDoc = await Role.findOne({ name: role });

    } else {

      roleDoc = await Role.findOne({ name: "User" });

    }

    if (!roleDoc) {

      return errorResponse(res, "Role not found", 404);

    }

    const newUser = new User({
      firstName,
      lastName,
      email,
      password: hashedPassword,
      phone,
      // role: role || "user",
      role: roleDoc._id,
      orgId,
      gender: gender || "other",
      department: department || null,
      designation: designation || null,
      employeeId: employeeId || null,
      // status: status !== undefined ? status : true,
      salary,
      workingDays: workingDays || 30,
      workingHours,
      // workingHours: workingHours || 8,
      employeeType: employeeType || "full-time",
      reportingManager: reportingManager || null,

      status: "Pending",
      address: parsedAddress,
      profileImage, // ✅ STORED
      specializations: parsedSpecializations,
      consultationFee,
    });

    // here need to add validation for reporting manager belongs to same org or not or for self reporting manager

    const savedUser = await newUser.save();

    const token = jwt.sign(
      { userId: savedUser._id, role: savedUser.role },
      process.env.JWT_SECRET,
      { expiresIn: "30d" }
    );

    await logUserAction({
      userId: savedUser._id,
      action: "REGISTER",
      model: "User",
      details: { email, firstName, lastName },
      req,
    });

    return res.status(201).json({
      success: true,
      message: "User registered successfully",
      data: {
        user: savedUser,
        token,
      },
    });
  } catch (err) {
    console.error("Register user error:", err);
    return errorResponse(res, "Failed to register user", 500, err);
  }
};

// future use ...since added shift/branch fields in users
// const registerUser = async (req, res) => {
//   try {
//     const {
//       firstName,
//       lastName,
//       email,
//       password,
//       phone,
//       orgId,
//       gender,
//       department,
//       designation,
//       employeeId,
//       address,
//       branch,
//       shift,
//     } = req.body;

//     // 1️⃣ BASIC VALIDATION
//     if (!firstName || !email || !password || !orgId || !branch || !shift) {
//       return errorResponse(
//         res,
//         "First name, email, password, organization, branch and shift are required",
//         400
//       );
//     }

//     // 2️⃣ CHECK EXISTING USER
//     const existingUser = await User.findOne({ email });
//     if (existingUser) {
//       return errorResponse(res, "Email already in use", 400);
//     }

//     // 3️⃣ VALIDATE BRANCH
//     const branchDoc = await Branch.findOne({
//       _id: branch,
//       orgId,
//       isDeleted: false,
//     });

//     if (!branchDoc) {
//       return errorResponse(res, "Invalid or inactive branch", 400);
//     }

//     // 4️⃣ VALIDATE SHIFT
//     const shiftDoc = await Shift.findOne({
//       _id: shift,
//       orgId,
//       isDeleted: false,
//     });

//     if (!shiftDoc) {
//       return errorResponse(res, "Invalid or inactive shift", 400);
//     }

//     // 5️⃣ HASH PASSWORD
//     const hashedPassword = await bcrypt.hash(password, 10);

//     // 6️⃣ HANDLE IMAGE
//     const profileImage = req.file
//       ? `/uploads/images/${req.file.filename}`
//       : null;

//     // 7️⃣ PARSE ADDRESS SAFELY
//     let parsedAddress = {};
//     if (address) {
//       try {
//         parsedAddress =
//           typeof address === "string" ? JSON.parse(address) : address;
//       } catch {
//         parsedAddress = {};
//       }
//     }

//     // 8️⃣ CREATE USER
//     const newUser = new User({
//       firstName,
//       lastName,
//       email,
//       password: hashedPassword,
//       phone,
//       role: "user",
//       orgId,
//       branch,
//       shift,
//       gender: gender || "other",
//       department: department || null,
//       designation: designation || null,
//       employeeId: employeeId || null,
//       status: "Pending",
//       address: parsedAddress,
//       profileImage,
//     });

//     const savedUser = await newUser.save();

//     // 9️⃣ JWT (INCLUDE orgId FOR FUTURE FILTERING)
//     const token = jwt.sign(
//       {
//         userId: savedUser._id,
//         role: savedUser.role,
//         orgId: savedUser.orgId,
//       },
//       process.env.JWT_SECRET,
//       { expiresIn: "30d" }
//     );

//     // 🔟 AUDIT LOG
//     await logUserAction({
//       userId: savedUser._id,
//       action: "REGISTER",
//       model: "User",
//       details: {
//         email,
//         firstName,
//         lastName,
//         branch: branchDoc.branchName,
//         shift: shiftDoc.shiftName,
//       },
//       req,
//     });

//     return res.status(201).json({
//       success: true,
//       message: "User registered successfully",
//       data: {
//         user: savedUser,
//         token,
//       },
//     });
//   } catch (err) {
//     console.error("Register user error:", err);
//     return errorResponse(res, "Failed to register user", 500, err);
//   }
// };


// const registerUser = async (req, res) => {
//   try {
//     const {
//       firstName,
//       lastName,
//       email,
//       password,
//       phone,
//       orgId,
//       gender,
//       department,
//       designation,
//       employeeId,
//       address,
//     } = req.body;

//     if (!firstName || !email || !password || !orgId) {
//       return errorResponse(
//         res,
//         "First name, email, password and organization ID are required",
//         400
//       );
//     }

//     const existingUser = await User.findOne({ email });
//     if (existingUser) {
//       return errorResponse(res, "Email already in use", 400);
//     }

//     const hashedPassword = await bcrypt.hash(password, 10);

//     const profileImage = req.file
//       ? `/uploads/images/${req.file.filename}`
//       : null;

//     let parsedAddress = {};
//     if (address) {
//       try {
//         parsedAddress = typeof address === "string" ? JSON.parse(address) : address;
//       } catch {
//         parsedAddress = {};
//       }
//     }

//     const newUser = new User({
//       firstName,
//       lastName,
//       email,
//       password: hashedPassword,
//       phone,
//       role: "user",                 // ✅ FIXED
//       orgId,
//       gender: gender || "other",
//       department: department || null,
//       designation: designation || null,
//       employeeId: employeeId || null,
//       status: "Pending",            // ✅ FIXED
//       createdBy: req.user?._id,     // ✅ ADDED
//       address: parsedAddress,
//       profileImage,
//     });

//     const savedUser = await newUser.save();

//     const token = jwt.sign(
//       { userId: savedUser._id, role: savedUser.role },
//       process.env.JWT_SECRET,
//       { expiresIn: "30d" }
//     );

//     await logUserAction({
//       userId: savedUser._id,
//       action: "REGISTER",
//       model: "User",
//       details: { email, firstName, lastName },
//       req,
//     });

//     return res.status(201).json({
//       success: true,
//       message: "User registered successfully",
//       data: {
//         user: savedUser,
//         token,
//       },
//     });
//   } catch (err) {
//     console.error("Register user error:", err);
//     return errorResponse(res, "Failed to register user", 500, err);
//   }
// };




// ------------------ LOGIN ------------------

// const loginUser = async (req, res) => {
//   try {
//     const { email, password } = req.body;
//     if (!email || !password)
//       return errorResponse(res, "Email and password are required", 400);

//     const user = await User.findOne({ email })
//       .populate("role", "name permissions");
//     if (!user) return errorResponse(res, "Invalid email or password", 401);

//     const isMatch = await bcrypt.compare(password, user.password);
//     if (!isMatch) return errorResponse(res, "Invalid email or password", 401);

//     // Update last login
//     user.lastLogin = new Date();

//     // Device info from headers (mobile)
//     user.deviceId = req.headers["x-device-id"] || user.deviceId;
//     user.deviceModel = req.headers["x-device-model"] || user.deviceModel || req.headers["user-agent"];
//     user.appVersion = req.headers["x-app-version"] || user.appVersion || "Browser";
//     user.deviceToken = req.headers["x-device-token"] || user.deviceToken; // only for mobile
//     user.playerId = req.headers["x-player-id"] || user.playerId; // only for mobile

//     await user.save();
//     console.log("USER ROLE:", user);

//     const token = jwt.sign(
//       // { userId: user._id, role: user.role },
//       {
//         userId: user._id,
//         roleId: user.role._id,
//       },
//       process.env.JWT_SECRET,
//       { expiresIn: "30d" }
//     );

//     await logUserAction({
//       userId: user._id,
//       action: "LOGIN",
//       model: "User",
//       details: { email },
//       req
//     });

//     return res.json({
//       success: true,
//       message: "Login successful",
//       user,
//       token,
//     });
//   } catch (err) {
//     return errorResponse(res, "Failed to login", 500, err);
//   }
// };

// ------------------ LOGIN ------------------
const loginUser = async (req, res) => {
  try {
    const { email, password } = req.body;
    if (!email || !password)
      return errorResponse(res, "Email and password are required", 400);

    const user = await User.findOne({ email })
      .populate("role", "name permissions");

    if (!user) return errorResponse(res, "Invalid email or password", 401);

    const isMatch = await bcrypt.compare(password, user.password);
    if (!isMatch) return errorResponse(res, "Invalid email or password", 401);

    // Update last login
    user.lastLogin = new Date();
    await user.save();

    console.log("✅ Login - User orgId:", user.orgId);

    // ✅ CRITICAL: Create session with orgId
    req.session.user = {
      id: user._id,
      userId: user._id,
      email: user.email,
      firstName: user.firstName,
      lastName: user.lastName,
      role: user.role?.name || user.role,
      orgId: user.orgId,           // ← This was missing!
    };

    // Force save session
    await new Promise((resolve, reject) => {
      req.session.save((err) => {
        if (err) reject(err);
        else resolve();
      });
    });

    // Optional: Also generate JWT with orgId (for future)
    const token = jwt.sign(
      {
        userId: user._id,
        roleId: user.role?._id,
        orgId: user.orgId,           // ← Add this too
      },
      process.env.JWT_SECRET,
      { expiresIn: "30d" }
    );

    await logUserAction({
      userId: user._id,
      action: "LOGIN",
      model: "User",
      details: { email },
      req
    });

    return res.json({
      success: true,
      message: "Login successful",
      user: {
        id: user._id,
        firstName: user.firstName,
        lastName: user.lastName,
        email: user.email,
        role: user.role?.name || user.role,
        orgId: user.orgId
      },
      token,   // if frontend needs it
    });
  } catch (err) {
    console.error("Login error:", err);
    return errorResponse(res, "Failed to login", 500, err);
  }
};


// ------------------ VALIDATE TOKEN ------------------

const validateToken = async (req, res) => {
  try {
    let token = req.headers.authorization;
    if (token && token.startsWith("Bearer ")) {
      token = token.split(" ")[1];
    }
    if (!token) return errorResponse(res, "No token provided", 401);

    let decoded;
    try {
      decoded = jwt.verify(token, process.env.JWT_SECRET);
    } catch (err) {
      return errorResponse(res, "Invalid or expired token", 401);
    }

    const user = await User.findById(decoded.userId).select("-password");
    if (!user) return errorResponse(res, "User not found", 404);

    // Optional: Log token validation
    await logUserAction({
      userId: user._id,
      action: "VALIDATE_TOKEN",
      model: "User",
      details: { tokenValid: true },
      req,
    });

    return res.json({
      success: true,
      message: "Token is valid",
      user
    });
  } catch (err) {
    return errorResponse(res, "Failed to validate token", 500, err);
  }
};

// ------------------ GET ALL USERS ------------------
const getAllUsers = async (req, res) => {
  try {
    let { page = 1, limit = 10 } = req.query;
    page = parseInt(page);
    limit = parseInt(limit);
    const skip = (page - 1) * limit;

    const [users, total] = await Promise.all([
      // User.find({ isDeleted: false }) .populate("role", "name permissions").select("-password").skip(skip).limit(limit).sort({ createdAt: -1 }),
      User.find({ isDeleted: false }).populate("branch", "branchName address.city status")
        .populate("createdBy", "firstName lastName role")
        .populate("updatedBy", "firstName lastName role")
        .sort({ createdAt: -1 })
        .populate("department", "deptName status")
        .populate("reportingManager", "firstName lastName role")
        .populate("shift", "shiftName startTime endTime").select("-password").skip(skip).limit(limit).sort({ createdAt: -1 }),

      User.countDocuments({ isDeleted: false }),
    ]);
    // console.log("REQ.USER IN getAllUsers:", req.user);


    await logUserAction({
      userId: req.user?._id,
      // userId: req.user.id,
      action: "READ",
      model: "User",
      details: { page, limit, count: users.length },
      req
    });

    return res.json({
      success: true,
      total,
      page,
      totalPages: Math.ceil(total / limit),
      data: users,
    });
  } catch (err) {
    return errorResponse(res, "Failed to fetch users", 500, err);
  }
};

// ------------------ GET USER BY ID ------------------
const getUserById = async (req, res) => {
  try {
    const user = await User.findById(req.params.id)
      .populate("branch", "branchName address.city")
      .populate("shift", "shiftName startTime endTime")
    // .select("-password");
    if (!user) return errorResponse(res, "User not found", 404);

    await logUserAction({
      // userId : req.user?.id,
      userId: req.user?.id,
      action: "READ",
      model: "User",
      details: { userId: user._id },
      req
    });

    return res.json(user);
  } catch (err) {
    return errorResponse(res, "Failed to fetch user", 500, err);
  }
};

// ------------------ UPDATE USER ------------------
const updateUser = async (req, res) => {
  try {
    const updates = { ...req.body, updatedBy: req.user?._id || null };
    const user = await User.findByIdAndUpdate(req.params.id, updates, { new: true });
    if (!user) return errorResponse(res, "User not found", 404);

    await logUserAction({
      userId: req.user?._id,
      action: "UPDATE",
      model: "User",
      details: { userId: user._id, updates },
      req
    });

    return res.json({
      success: true,
      message: "User updated successfully",
      data: user,
    });
  } catch (err) {
    return errorResponse(res, "Failed to update user", 500, err);
  }
};

// delete user controller
const deleteUser = async (req, res) => {
  try {
    const user = await User.findByIdAndUpdate(req.params.id, { isDeleted: true }, { new: true });
    if (!user) return errorResponse(res, "User not found", 404);

    // log action
    await logUserAction({
      userId: req.user?._id,
      orgId: user.orgId || null,
      action: "DELETE",
      model: "User",
      details: { userId: user._id },
      req,
    });

    return res.json({
      success: true,
      message: "User deleted successfully",
    });
  } catch (err) {
    return errorResponse(res, "Failed to delete user", 500, err);
  }
}

// ------------------ DEACTIVATE USER ------------------
const deactivateUser = async (req, res) => {
  try {
    const user = await User.findByIdAndUpdate(req.params.id, { status: false }, { new: true });
    if (!user) return errorResponse(res, "User not found", 404);

    await logUserAction({
      userId: req.user?._id,
      action: "DEACTIVATE",
      model: "User",
      details: { userId: user._id },
      req
    });

    return res.json({
      success: true,
      message: "User deactivated successfully",
      data: user,
    });
  } catch (err) {
    return errorResponse(res, "Failed to deactivate user", 500, err);
  }
};

// ------------------ LOGOUT FROM DEVICE ------------------
const logoutFromDevice = async (req, res) => {
  try {
    const { userId, deviceId } = req.body;
    if (!userId || !deviceId) return errorResponse(res, "userId and deviceId are required", 400);

    const user = await User.findById(userId);
    if (!user) return errorResponse(res, "User not found", 404);

    if (user.deviceId === deviceId) {
      user.deviceId = null;
      user.deviceToken = null;
      user.playerId = null;
      await user.save();
    }

    await logUserAction({
      userId,
      action: "LOGOUT",
      model: "User",
      details: { deviceId },
      req
    });

    return res.json({
      success: true,
      message: "Logged out from device successfully",
      data: user,
    });
  } catch (err) {
    return errorResponse(res, "Failed to logout from device", 500, err);
  }
};

// ------------------ PROFILE IMAGE UPLOAD ------------------
const profileImageUpload = async (req, res) => {
  try {
    if (!req.file) {
      return errorResponse(res, "No file uploaded", 400);
    }

    const user = await User.findById(req.params.id);
    if (!user) {
      return errorResponse(res, "User not found", 404);
    }

    // ✅ Convert Windows path → web path
    const imagePath = `/uploads/images/${req.file.filename}`;

    user.profileImage = imagePath;
    await user.save();

    await logUserAction({
      userId: req.user?._id,
      action: "UPLOAD_PROFILE_IMAGE",
      model: "User",
      details: {
        userId: user._id,
        filePath: imagePath,
      },
      req,
    });

    return res.json({
      success: true,
      message: "Profile image uploaded successfully",
      data: {
        _id: user._id,
        profileImage: imagePath,
      },
    });
  } catch (err) {
    console.error("Profile image upload error:", err);
    return errorResponse(res, "Failed to upload profile image", 500, err);
  }
};


// ------------------ FORGOT PASSWORD ------------------
const forgotPassword = async (req, res) => {
  try {
    const { email, newPassword } = req.body;
    if (!email || !newPassword) return errorResponse(res, "Email and new password are required", 400);

    const user = await User.findOne({ email });
    if (!user) return errorResponse(res, "User not found", 404);

    user.password = await bcrypt.hash(newPassword, 10);
    await user.save();

    await logUserAction({
      userId: user._id,
      action: "RESET_PASSWORD",
      model: "User",
      details: { email },
      req
    });

    return res.json({
      success: true,
      message: "Password reset successfully",
    });
  } catch (err) {
    return errorResponse(res, "Failed to reset password", 500, err);
  }
};


const changePassword = async (req, res) => {
  try {
    const userId = req.user._id;
    const { currentPassword, newPassword, confirmPassword } = req.body;
    console.log(currentPassword);
    console.log(newPassword);



    if (!currentPassword || !newPassword || !confirmPassword) {
      return errorResponse(
        res,
        "Current password, new password and confirm password are required",
        400
      );
    }

    if (newPassword !== confirmPassword) {
      return errorResponse(res, "Passwords do not match", 400);
    }

    const user = await User.findById(userId).select("+password");
    if (!user) {
      return errorResponse(res, "User not found", 404);
    }

    //  IMPORTANT: await compare
    const isMatch = await bcrypt.compare(currentPassword, user.password);
    if (!isMatch) {
      return errorResponse(res, "Current password is incorrect", 400);
    }

    user.password = await bcrypt.hash(newPassword, 10);
    user.updatedAt = new Date();
    await user.save();

    //  audit log (same pattern as forgotPassword)
    await logUserAction({
      userId: user._id,
      action: "CHANGE_PASSWORD",
      model: "User",
      details: { userId: user._id },
      req,
    });

    return res.status(200).json({
      success: true,
      message: "Password changed successfully",
    });
  } catch (err) {
    return errorResponse(res, "Failed to change password", 500, err);
  }
};



// validate status update status
const updateUserStatus = async (req, res) => {
  try {
    const { status } = req.body;
    const userId = req.params.id;

    // ✅ Validate status
    if (!["Approved", "Rejected"].includes(status)) {
      return errorResponse(res, "Invalid status value", 400);
    }

    const user = await User.findById(userId);
    if (!user) {
      return errorResponse(res, "User not found", 404);
    }

    // ❌ Prevent re-approval
    if (user.status !== "Pending") {
      return errorResponse(
        res,
        `User already ${user.status}`,
        400
      );
    }

    // ✅ Update status
    user.status = status;
    user.updatedBy = req.user._id;

    await user.save();

    // ✅ Audit log
    await logUserAction({
      userId: req.user._id,
      action: status === "Approved" ? "APPROVE_USER" : "REJECT_USER",
      model: "User",
      details: {
        targetUserId: user._id,
        status,
      },
      req,
    });

    return res.json({
      success: true,
      message: `User ${status.toLowerCase()} successfully`,
      data: {
        id: user._id,
        status: user.status,
      },
    });
  } catch (err) {
    console.error("Update user status error:", err);
    return errorResponse(res, "Failed to update user status", 500, err);
  }
};

// fetchAgents controller
// const getAgents = async (req, res) => {
//   try {
//     const orgId = req.user?.orgId;
//     console.log(orgId);

//     const userId = req.user?._id;

//     if (!orgId) {
//       return errorResponse(res, "Organization context missing", 400);
//     }

//     const agents = await User.find({
//       role: "agent",
//       status: "Approved",
//       isDeleted: false,
//       orgId,
//     })
//       .select("_id firstName lastName phone email branch shift")
//       .populate("branch", "branchName")
//       .populate("shift", "shiftName startTime endTime")
//       .lean();

//     // console.log(agents);

//     // Audit log
//     await logUserAction({
//       userId,
//       orgId,
//       action: "READ",
//       model: "User",
//       details: { fetched: "agents", count: agents.length },
//       req,
//     });

//     return res.status(200).json({
//       success: true,
//       message: "Agents fetched successfully",
//       data: agents,
//     });
//   } catch (error) {
//     return errorResponse(res, "Failed to fetch agents", 500, error);
//   }
// };

// mobile api's
const sendAgentOtp = async (req, res) => {
  try {
    const { phone } = req.body;
    if (!phone) {
      return errorResponse(res, "Phone number required", 400);
    }

    const user = await User.findOne({
      phone,
      role: "agent",
      status: "Approved",
      isDeleted: false,
    });

    if (!user) {
      return errorResponse(
        res,
        "Agent not found or not approved",
        404
      );
    }

    const otp = Math.floor(100000 + Math.random() * 900000).toString();


    // await Otp.create({
    //   phone,
    //   otp: hashedOtp,
    //   expiresAt: new Date(Date.now() + 5 * 60 * 1000), // 5 min
    // });
    user.otp = otp;
    user.otpExpiresAt = new Date(Date.now() + 5 * 60 * 1000);
    await user.save();

    // ✅ clear old OTPs
    // await Otp.deleteMany({ phone });  future ref
    //  SMS integration later
    console.log("AGENT OTP:", otp);

    return res.json({
      success: true,
      message: "OTP sent successfully",
      data: otp
    });
  } catch (err) {
    return errorResponse(res, "Failed to send OTP", 500, err);
  }
};

// const verifyAgentOtp = async (req, res) => {
//   try {
//     const { phone, otp, deviceId, appVersion } = req.body;

//     if (!phone || !otp) {
//       return errorResponse(res, "Phone and OTP required", 400);
//     }

//     // const otpDoc = await Otp.findOne({ phone, otp });
//     // if (!otpDoc) {
//     //   return errorResponse(res, "Invalid or expired OTP", 401);
//     // }


//     // if (otpDoc.expiresAt < new Date()) {
//     //   await Otp.deleteMany({ phone });
//     //   return errorResponse(res, "OTP expired", 401);
//     // }
//     // const isValidOtp = await bcrypt.compare(otp, otpDoc.otp);
//     // if (!isValidOtp) {
//     //   return errorResponse(res, "Invalid OTP", 401);
//     // }

//     const user = await User.findOne({
//       phone,
//       role: "agent",
//       status: "Approved",
//       isDeleted: false,
//     });

//     if (!user) {
//       return errorResponse(res, "Agent not found", 404);
//     }

//     // Update login metadata
//     user.lastLogin = new Date();
//     user.deviceId = deviceId || user.deviceId;
//     user.appVersion = appVersion || user.appVersion;

//     await user.save();
//     await Otp.deleteMany({ phone }); // cleanup

//     const token = jwt.sign(
//       { userId: user._id, role: user.role },
//       process.env.JWT_SECRET,
//       { expiresIn: "30d" }
//     );

//     await logUserAction({
//       userId: user._id,
//       action: "LOGIN_OTP",
//       model: "User",
//       details: { phone },
//       req,
//     });

//     return res.json({
//       success: true,
//       message: "OTP verified successfully",
//       data: {
//         user,
//         token,
//       },
//     });
//   } catch (err) {
//     return errorResponse(res, "OTP verification failed", 500, err);
//   }
// };
// const verifyAgentOtp = async (req, res) => {
//   try {
//     const { phone, otp, deviceId, appVersion } = req.body;

//     if (!phone || !otp) {
//       return errorResponse(res, "Phone and OTP required", 400);
//     }

//     // const otpDoc = await Otp.findOne({ phone });
//     const otpDoc = await Otp.findOne({ phone })
//       .sort({ createdAt: -1 });

//     if (!otpDoc) {
//       return errorResponse(res, "Invalid or expired OTP", 401);
//     }

//     if (otpDoc.expiresAt < new Date()) {
//       await Otp.deleteMany({ phone });
//       return errorResponse(res, "OTP expired", 401);
//     }

//     const isValidOtp = await bcrypt.compare(otp, otpDoc.otp);
//     if (!isValidOtp) {
//       return errorResponse(res, "Invalid OTP", 401);
//     }

//     const user = await User.findOne({
//       phone,
//       role: "agent",
//       status: "Approved",
//       isDeleted: false,
//     });

//     if (!user) {
//       return errorResponse(res, "Agent not found or not approved", 404);
//     }

//     // Update login metadata
//     user.lastLogin = new Date();
//     user.deviceId = deviceId || user.deviceId;
//     user.appVersion = appVersion || user.appVersion;
//     await user.save();

//     // Cleanup OTPs
//     await Otp.deleteMany({ phone });

//     // Generate JWT
//     const token = jwt.sign(
//       { userId: user._id, role: user.role },
//       process.env.JWT_SECRET,
//       { expiresIn: "30d" }
//     );

//     await logUserAction({
//       userId: user._id,
//       action: "LOGIN_OTP",
//       model: "User",
//       details: { phone },
//       req,
//     });

//     return res.status(200).json({
//       success: true,
//       message: "OTP verified successfully",
//       data: {
//         user,
//         token,
//       },
//     });
//   } catch (err) {
//     console.error("VERIFY OTP ERROR:", err);
//     return errorResponse(res, "OTP verification failed", 500, err);
//   }
// };

const verifyAgentOtp = async (req, res) => {
  try {
    const { phone, otp, deviceId, appVersion, deviceToken } = req.body;

    if (!phone || !otp) {
      return errorResponse(res, "Phone and OTP required", 400);
    }

    const user = await User.findOne({
      phone,
      role: "agent",
      status: "Approved",
      isDeleted: false,
    });

    if (!user || !user.otp) {
      return errorResponse(res, "Invalid or expired OTP", 401);
    }

    // if (user.otpExpiresAt < new Date()) {
    //   user.otp = null;
    //   user.otpExpiresAt = null;
    //   await user.save();
    //   return errorResponse(res, "OTP expired", 401);
    // }

    if (user.otp !== otp) {
      return errorResponse(res, "Invalid OTP", 401);
    }

    // OTP verified → cleanup
    user.otp = null;
    user.otpExpiresAt = null;
    user.lastLogin = new Date();
    user.deviceId = deviceId || user.deviceId;
    user.deviceToken = deviceToken || user.deviceToken;
    user.appVersion = appVersion || user.appVersion;
    await user.save();

    const token = jwt.sign(
      { userId: user._id, role: user.role },
      process.env.JWT_SECRET,
      // { expiresIn: "30d" }
    );

    await logUserAction({
      userId: user._id,
      action: "LOGIN_OTP",
      model: "User",
      details: { phone },
      req,
    });

    return res.status(200).json({
      success: true,
      message: "OTP verified successfully",
      data: { user, token },
    });
  } catch (err) {
    console.error("VERIFY OTP ERROR:", err);
    return errorResponse(res, "OTP verification failed", 500, err);
  }
};



const resendAgentOtp = async (req, res) => {
  try {
    const { phone } = req.body;
    if (!phone) {
      return errorResponse(res, "Phone number required", 400);
    }

    const user = await User.findOne({
      phone,
      role: "agent",
      status: "Approved",
      isDeleted: false,
    });

    if (!user) {
      return errorResponse(res, "Agent not found or not approved", 404);
    }
    // OPTIONAL: cooldown (30 sec) for future ref
    // if (user.otpExpiresAt && user.otpExpiresAt > new Date(Date.now() - 30 * 1000)) {
    //   return errorResponse(res, "Please wait before resending OTP", 429);
    // }
    const otp = Math.floor(100000 + Math.random() * 900000).toString();

    user.otp = otp;
    user.otpExpiresAt = new Date(Date.now() + 5 * 60 * 1000);
    await user.save();


    console.log("RESEND OTP:", otp);

    return res.json({
      success: true,
      message: "OTP resent successfully",
      data: otp
    });
  } catch (err) {
    return errorResponse(res, "Failed to resend OTP", 500, err);
  }
};

const getAgentProfile = async (req, res) => {
  try {
    const agentId = req.user._id;

    const user = await User.findOne({
      _id: agentId,
      role: "agent",
      isDeleted: false,
    }).select(
      "firstName lastName phone email gender address profileImage updatedAt"
    );

    if (!user) {
      return errorResponse(res, "Agent not found", 404);
    }

    await logUserAction({
      userId: agentId,
      action: "GET_AGENT_PROFILE",
      model: "User",
      details: {
        fetchedFields: [
          "firstName",
          "lastName",
          "phone",
          "email",
          "gender",
          "address",
          "profileImage",
        ],
      },
      req,
    });

    return res.status(200).json({
      success: true,
      message: "Agent profile fetched successfully",
      data: {
        _id: user._id,
        name: `${user.firstName} ${user.lastName || ""}`.trim(),
        firstName: user.firstName,
        lastName: user.lastName || "",
        phone: user.phone || "",
        email: user.email || "",
        gender: user.gender || "other",
        address: user.address || {},
        profileImage: user.profileImage || null,
        updatedAt: user.updatedAt,
      },
    });
  } catch (err) {
    console.error("GET AGENT PROFILE ERROR:", err);
    return errorResponse(res, "Failed to fetch agent profile", 500, err);
  }
};


const updateAgentProfileDetails = async (req, res) => {
  try {
    const agentId = req.user._id;


    const allowedFields = [
      "firstName",
      "lastName",
      "email",
      "phone",
      "gender",
      "address",
    ];

    const updates = {};

    allowedFields.forEach((field) => {
      if (req.body[field] !== undefined) {
        updates[field] = req.body[field];
      }
    });

    // if (Object.keys(updates).length === 0) {
    //   return errorResponse(res, "No valid fields provided", 400);
    // }

    updates.updatedAt = new Date();

    const user = await User.findOneAndUpdate(
      {
        _id: agentId,
        role: "agent",
        isDeleted: false,
      },
      { $set: updates },
      { new: true }
    ).select("-password -deviceToken -playerId");

    if (!user) {
      return errorResponse(res, "Agent not found", 404);
    }

    await logUserAction({
      userId: agentId,
      action: "UPDATE_PROFILE_DETAILS",
      model: "User",
      details: { updatedFields: Object.keys(updates) },
      req,
    });

    return res.status(200).json({
      success: true,
      message: "Profile details updated successfully",
      data: user,
    });
  } catch (err) {
    console.error("UPDATE AGENT PROFILE DETAILS ERROR:", err);
    return errorResponse(res, "Failed to update profile details", 500, err);
  }
};


const updateAgentProfileImage = async (req, res) => {
  try {
    const agentId = req.user._id;

    // if (!req.file) {
    //   return errorResponse(res, "Profile image is required", 400);
    // }

    const profileImagePath = `/uploads/images/${req.file.filename}`;

    const user = await User.findOneAndUpdate(
      {
        _id: agentId,
        role: "agent",
        isDeleted: false,
      },
      {
        $set: {
          profileImage: profileImagePath,
          updatedAt: new Date(),
        },
      },
      { new: true }
    ).select("-password -deviceToken -playerId");

    if (!user) {
      return errorResponse(res, "Agent not found", 404);
    }

    await logUserAction({
      userId: agentId,
      action: "UPDATE_PROFILE_IMAGE",
      model: "User",
      details: {
        profileImage: profileImagePath,
      },
      req,
    });

    return res.status(200).json({
      success: true,
      message: "Profile image updated successfully",
      data: {
        profileImage: user.profileImage,
      },
    });
  } catch (err) {
    console.error("UPDATE AGENT PROFILE IMAGE ERROR:", err);
    return errorResponse(res, "Failed to update profile image", 500, err);
  }
};


const getAgentProfileWithHistory = async (req, res) => {
  try {
    const agentId = req.user._id;
    const orgId = req.user.orgId;

    /*  AGENT PROFILE */
    const agent = await User.findOne({
      _id: agentId,
      role: "agent",
      isDeleted: false,
    }).select(
      "firstName lastName phone profileImage address"
    );

    if (!agent) {
      return res.status(404).json({
        success: false,
        message: "Agent not found",
      });
    }

    /*  HISTORY */
    const history = await Task.find({
      assignedTo: agentId,
      orgId,
      isDeleted: false,
      status: { $in: ["Completed", "Closed"] },
    })
      .select("customer completedAt")
      .sort({ completedAt: -1 })
      .limit(20); // production-safe limit

    return res.status(200).json({
      success: true,
      data: {
        agent: {
          name: `${agent.firstName} ${agent.lastName || ""}`.trim(),
          phone: agent.phone,
          profileImage: agent.profileImage || null,
          address: agent.address || null,
        },
        history: history.map((task) => ({
          customerName: task.customer?.name || "--",
          address: task.customer?.address || "--",
          completedAt: task.completedAt,
        })),
      },
    });
  } catch (err) {
    console.error("GET AGENT PROFILE HISTORY ERROR:", err.message, err);
    return res.status(500).json({
      success: false,
      message: "Failed to fetch agent profile",
    });
  }
};

// const getUsers = async (req, res) => {
//   try {
//     const { role, page = 1, limit = 20 } = req.query;
//     const orgId = req.user.orgId;

//     const query = {
//       role : "doctor",
//       orgId,
//       isDeleted: false,
//     };

//     // Optional role filter
//     if (role) {
//       query.role = role;
//     }

//     const skip = (page - 1) * limit;

//     const [users, total] = await Promise.all([
//       User.find(query)
//         .select("firstName lastName email phone role status")
//         .sort({ createdAt: -1 })
//         .skip(skip)
//         .limit(Number(limit)),

//       User.countDocuments(query),
//     ]);

//     return res.status(200).json({
//       success: true,
//       total,
//       page: Number(page),
//       limit: Number(limit),
//       data: users,
//     });
//   } catch (error) {
//     console.error("getUsers error:", error);
//     return errorResponse(res, "Failed to fetch users", 500);
//   }
// };
const getUsers = async (req, res) => {
  try {
    const { page = 1, limit = 20 } = req.query;
    const orgId = req.user.orgId;

    const query = {
      role: "doctor",
      orgId,
      isDeleted: false,
    };

    const skip = (page - 1) * limit;

    const [users, total] = await Promise.all([
      User.find(query)
        .populate("specializations", "name")
        .populate("branch", "branchName")
        .select("firstName lastName email phone role status specializations branch consultationFee workingHours lunchBreak")
        .sort({ createdAt: -1 })
        .skip(skip)
        .limit(Number(limit)),

      User.countDocuments(query),
    ]);

    return res.status(200).json({
      success: true,
      total,
      page: Number(page),
      limit: Number(limit),
      data: users,
    });
  } catch (error) {
    console.error("getDoctors error:", error);
    return errorResponse(res, "Failed to fetch doctors", 500);
  }
};

const getDoctorProfile = async (req, res) => {
  try {
    const { id } = req.params;

    //  Validate Mongo ID
    // if (!mongoose.Types.ObjectId.isValid(id)) {
    //   return errorResponse(res, 400, "Invalid doctor id");
    // }

    //  Fetch only if role is doctor
    const doctor = await User.findOne({
      _id: id,
      role: "doctor",
      isDeleted: { $ne: true },
    })
      .select(
        "firstName lastName phone email profileImage specialization experience education languages about designation"
      )
      .populate("designation", "name")
      .lean();

    if (!doctor) {
      return errorResponse(res, 404, "Doctor not found");
    }

    //  Safe defaults for frontend
    const response = {
      id: doctor._id,
      firstName: doctor.firstName,
      lastName: doctor.lastName,
      phone: doctor.phone,
      email: doctor.email,
      profileImage: doctor.profileImage,
      designation: doctor.designation?.name || "Consultant",
      specialization: doctor.specialization || "General Physician",
      experience: doctor.experience || "5 Years",
      education: doctor.education || "MBBS",
      languages: doctor.languages?.length ? doctor.languages : ["English"],
      about: doctor.about || "Experienced medical professional",
    };

    return res.status(200).json({
      success: true,
      message: "Doctor profile fetched successfully",
      data: response,
    });
  } catch (error) {
    console.error("Get Doctor Profile Error:", error);
    return errorResponse(res, 500, "Internal server error");
  }
};


module.exports = {
  registerUser,
  loginUser,
  getAllUsers,
  getUserById,
  updateUser,
  deactivateUser,
  logoutFromDevice,
  profileImageUpload,
  forgotPassword,
  validateToken,
  deleteUser,
  forgotPassword,
  updateUserStatus,
  // getAgents,
  sendAgentOtp,
  verifyAgentOtp,
  resendAgentOtp,
  getAgentProfile,
  updateAgentProfileDetails,
  updateAgentProfileImage,
  changePassword,
  getAgentProfileWithHistory,
  getUsers,
  getDoctorProfile,

};
