const jwt = require("jsonwebtoken")
const bcrypt = require("bcrypt")
const faker = require("faker")
const User = require("../model/User")
const auth = require("../auth")

// Secret Sauce
require("dotenv").config()

// Controller function for user registration
exports.registerUser = async (req, res) => {
	try {
		const { email, password, firstName, lastName } = req.body

		// Check if the email already exists
		const existingUser = await User.findOne({ email })

		if (existingUser) {
			return res
				.status(400)
				.json({ message: "This Email is already registered." })
		}

		// If firstName and lastName are not provided, generate default values using faker
		const autoGeneratedFirstName = firstName || faker.name.firstName()
		const autoGeneratedLastName = lastName || faker.name.lastName()

		// Hash the password before saving it
		const hashedPassword = await bcrypt.hash(password, 10)

		const newUser = new User({
			email,
			password: hashedPassword,
			firstName: autoGeneratedFirstName,
			lastName: autoGeneratedLastName,
		})

		await newUser.save()

		res.status(201).json({
			message:
				"User registered successfully. To update account details, acess user/update",
		})
	} catch (error) {
		console.error(error)
		res.status(500).json({ message: "Internal server error" })
	}
}

// Controller function for user authentication
exports.authenticateUser = async (req, res) => {
	try {
		const { email, password } = req.body

		const user = await User.findOne({ email })

		if (!user) {
			return res.status(401).json({ message: "Invalid credentials" })
		}

		const passwordMatch = await bcrypt.compare(password, user.password)

		if (!passwordMatch) {
			return res.status(401).json({ message: "Invalid credentials" })
		}

		// Generate JWT token using the function from auth.js
		const token = auth.generateToken(user._id, user.email, user.isAdmin)

		// Decode JWT token to get expiration time
		const decodedToken = jwt.decode(token)

		if (decodedToken) {
			const expiration = new Date(decodedToken.exp * 1000) // Convert seconds to milliseconds
			// Log token expiration
			console.log(
				`Authenticate success. Token will expire on: ${expiration}`
			)
		} else {
			console.error("Error decoding token")
		}

		// Return user details and token
		res.status(200).json({
			userId: user._id,
			email: user.email,
			firstName: user.firstName,
			lastName: user.lastName,
			isAdmin: user.isAdmin,
			token: token,
		})
	} catch (error) {
		console.error(error)
		res.status(500).json({ message: "Internal server error" })
	}
}

// Controller function for updating user data (including email, firstName, lastName, and password)
exports.updateUserData = async (req, res) => {
	try {
		const { userId, newEmail, newFirstName, newLastName, newPassword } =
			req.body

		const userIdFromToken = req.user.userId
		if (userIdFromToken !== userId) {
			return res.status(403).json({
				message:
					"Permission denied. You can only update your own data.",
			})
		}

		const user = await User.findById(userId)

		if (!user) {
			return res.status(404).json({ message: "User not found" })
		}

		// Update email if provided
		if (newEmail) {
			user.email = newEmail
		}

		// Update firstName if provided
		if (newFirstName) {
			user.firstName = newFirstName
		}

		// Update lastName if provided
		if (newLastName) {
			user.lastName = newLastName
		}

		// Update password if provided
		if (newPassword) {
			const hashedPassword = await bcrypt.hash(newPassword, 10)
			user.password = hashedPassword
		}

		// Save the updated user data
		await user.save()

		// Fetch the updated user details
		const updatedUser = await User.findById(userId)

		// Return the updated user details in the response
		res.status(200).json({
			message: "User data updated successfully",
			user: updatedUser,
		})
	} catch (error) {
		console.error(error)
		res.status(500).json({ message: "Internal server error" })
	}
}

exports.getUserDetails = async (req, res) => {
	try {
	  const { userId } = req.body;
  
	  const user = await User.findById(userId);
  
	  if (!user) {
		return res.status(404).json({ message: "User not found" });
	  }
  
	  // Create a new object with only the desired properties (excluding password)
	  const userWithoutPassword = {
		_id: user._id,
		username: user.username,
		email: user.email,
		firstName: user.firstName,
		lastName: user.lastName,
		orderedProducts: user.orderedProducts,
		// Add other properties you want to include in the response
	  };
  
	  // Return the user details in the response
	  res.status(200).json({
		user: userWithoutPassword,
	  });
	} catch (error) {
	  console.error(error);
	  res.status(500).json({ message: false });
	}
  };
  
  

exports.setAdmin = async (req, res) => {
	try {
		const { userId } = req.body // assuming userId is sent in the request body

		const user = await User.findById(userId)

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

		user.isAdmin = true
		await user.save()

		res.json({ message: "User is now an admin." })
	} catch (error) {
		console.error(error)
		res.status(500).json({ error: "Internal server error" })
	}
}

