const express = require("express");
const session = require("express-session");
const rateLimit = require('express-rate-limit');
const mysql2 = require('mysql2');
const bodyParser = require("body-parser");
const bcrypt = require("bcrypt");
const crypto = require("crypto");
const nodemailer = require("nodemailer");
const otpGenerator = require('otp-generator');
const { body, validationResult } = require('express-validator');
const validator = require('validator');

const { transporter } = require("./modules/nodeMailer");
const { connection } = require("./modules/mysql"); 

const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
const PORT = process.env.PORT || 3000;
require("dotenv").config();

app.use(bodyParser.urlencoded({ extended: true }));

app.set("view engine", "ejs");

app.use(session({
    secret: process.env.key,
    resave: false,
    saveUninitialized: true,
    cookie: {
        secure: false, // Make sure to set this to true in a production environment with HTTPS
        httpOnly: true,
        maxAge: 24 * 60 * 60 * 1000, // Session duration in milliseconds (here set to 1 day)
    },
}));
function isAuthenticated(req, res, next) {
	if (req.session && req.session.authenticated) {
		return next();
	} else {
		res.redirect("/login");
	}
}
const generateOTP = () => {
	const otp = otpGenerator.generate(6, { upperCase: false, specialChars: false });
	const expirationTime = Date.now() + 5 * 60 * 1000; // 5 minutes expiration
	return { otp, expirationTime };
  };

const sendOTPByEmail = async (email, otp) => {
	try {
	  const transporter = nodemailer.createTransport({
		service: 'gmail',
		auth: {
		  user: process.env.euser,  // replace with your email
		  pass: process.env.epass   // replace with your email password
		}
	  });
  
	  const mailOptions = {
		from: process.env.euser,
		to: email,
		subject: 'Login OTP',
		text: `Your OTP for login is: ${otp}`
	  };
  
	  await transporter.sendMail(mailOptions);
	  console.log('OTP sent successfully to', email);
	} catch (error) {
	  console.error('Error sending OTP:', error);
	  throw error;
	}
  };


app.get("/login", (req, res) => {
	
	res.render("login", { error: null });
});

const logActivity = async (username, success, message) => {
	try {
	  if (!username) {
		console.error("Error logging activity: Username is null or undefined");
		return;
	  }
  
	  const activity = success ? `successful login: ${message}` : `unsuccessful login: ${message}`;
	  const logSql =
		"INSERT INTO user_logs (username, activity, timestamp) VALUES (?, ?, CURRENT_TIMESTAMP)";
	  const logParams = [username, activity];
  
	  connection.query(logSql, logParams, (error, results) => {
		if (error) {
		  console.error("Error executing logSql:", error);
		  // Handle error (you may want to log it or take other appropriate actions)
		} else {
		  console.log("Activity logged successfully");
		}
	  });
	} catch (error) {
	  console.error("Error in logActivity function:", error);
	  // Handle error (you may want to log it or take other appropriate actions)
	}
  };
  
  const logLogoutActivity = async (username, success, message) => {
	try {
	  if (!username) {
		console.error("Error logging activity: Username is null or undefined");
		return;
	  }
  
	  const activity = success ? `successful logout: ${message}` : `unsuccessful logout: ${message}`;
	  const logSql =
		"INSERT INTO user_logs (username, activity, timestamp) VALUES (?, ?, CURRENT_TIMESTAMP)";
	  const logParams = [username, activity];
  
	  connection.query(logSql, logParams, (error, results) => {
		if (error) {
		  console.error("Error executing logSql:", error);
		  // Handle error (you may want to log it or take other appropriate actions)
		} else {
		  console.log("Activity logged successfully");
		}
	  });
	} catch (error) {
	  console.error("Error in logActivity function:", error);
	  // Handle error (you may want to log it or take other appropriate actions)
	}
  };


  const limiter = rateLimit({
	windowMs: 15 * 60 * 1000, // 15 minutes
	max: 5, // limit each IP to 3 requests per windowMs
	message: 'Too many login attempts from this IP, please try again later.',
  });
  app.use('/login', limiter);
  
  app.post('/login', [
    body('username').escape().trim().isLength({ min: 1 }).withMessage('Username must not be empty'),
    body('password').escape().trim().isLength({ min: 1 }).withMessage('Password must not be empty'),
],
async (req, res) => {
    try {
        const errors = validationResult(req);

        if (!errors.isEmpty()) {
            // Handle validation errors, e.g., return an error message to the client
            return res.render('login', { error: 'Invalid input. Please check your credentials.', csrfToken: req.session.csrfToken });
        }

        let { username, password } = req.body;
        username = username.trim();

        const loginSql = "SELECT * FROM users WHERE username = ?";

        connection.query(loginSql, [username], async (error, results) => {
            if (error) {
                console.error("Error executing login query:", error);
                res.status(500).send("Internal Server Error");
                return;
            }

            if (results.length > 0) {
                const isLoginSuccessful = await bcrypt.compare(password, results[0].password);

                if (isLoginSuccessful) {
                    // Log successful login attempt
                    await logActivity(username, true, "Credentials entered correctly");

                    const user = results[0];
                    const { otp, expirationTime } = generateOTP();

                    // Store the OTP and expiration time in the session for verification
                    req.session.otp = otp;
                    req.session.otpExpiration = expirationTime;
                    req.session.save();

                    // Send OTP via email
                    try {
                        await sendOTPByEmail(user.email, otp);
                        // Log successful OTP sending
                        await logActivity(username, true, "OTP successfully sent to user");
                    } catch (sendOTPError) {
                        // Log unsuccessful OTP sending
                        await logActivity(username, false, "OTP failed to send to user");
                        console.error("Error sending OTP:", sendOTPError);
                        res.status(500).send("Internal Server Error");
                        return;
                    }

                    // Render OTP input page
                    res.render("otp", { error: null, username: user.username, csrfToken: req.session.csrfToken });
                } else {
                    // Log unsuccessful login attempt
                    await logActivity(username, false, "Incorrect password");
                    res.render("login", { error: "Invalid username or password", csrfToken: req.session.csrfToken });
                }
            } else {
                // Log unsuccessful login attempt
                await logActivity(username, false, "User not found");
                res.render("login", { error: "Invalid username or password", csrfToken: req.session.csrfToken });
            }
        });
    } catch (error) {
        console.error("Error in login route:", error);
        res.status(500).send("Internal Server Error");
    }
});

// OTP verification route
app.post("/verify-otp", [
    body('otp').escape().trim().isLength({ min: 1 }).withMessage('OTP must not be empty'),
],
async (req, res) => {
    try {
        const errors = validationResult(req);

        if (!errors.isEmpty()) {
            // Handle validation errors, e.g., return an error message to the client
            return res.render('otp', { error: 'Invalid OTP. Please try again.', username: req.body.username, csrfToken: req.session.csrfToken });
        }

        const enteredOTP = req.body.otp;

        if (!req.session) {
            // If session is not defined, handle accordingly
            console.error("Session is not defined.");
            return res.status(500).send("Internal Server Error");
        }

        if (enteredOTP === req.session.otp) {
            // Log successful OTP entry
            if (req.body.username) {
                await logActivity(req.body.username, true, "OTP entered correctly");
            }

            // Correct OTP, generate a session token
            const sessionToken = crypto.randomBytes(32).toString('hex');

            // Store the session token in the session
            req.session.authenticated = true;
            req.session.username = req.body.username;
            req.session.sessionToken = sessionToken;

            // Generate and store anti-CSRF token in the session
            csrfTokensession = crypto.randomBytes(32).toString('hex');

            // Set anti-CSRF token in res.locals
            

            // Log anti-CSRF token
            console.log(`Generated Anti-CSRF Token: ${csrfTokensession}`);
			// Set CSRF token as a cookie
          
            // Implement secure session handling:
            // 1. Set secure, HttpOnly, and SameSite flags
            // 2. Set an expiration time for the session token
            // 3. Regenerate the session after authentication
            res.cookie('sessionToken', sessionToken, { secure: true, httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000) }); // Expires in 1 day

            console.log(`Generated Session Token: ${sessionToken}`);

            // Redirect to home page with session token
            res.redirect("/home");
        } else {
            // Log unsuccessful OTP entry
            if (req.body.username) {
                await logActivity(req.body.username, false, "Incorrect OTP entered");
            }

            // Incorrect OTP, render login page with error
            res.render("login", { error: "Incorrect OTP. Please try again.", csrfToken: req.session.csrfToken });
        }
    } catch (error) {
        console.error("Error in OTP verification route:", error);
        res.status(500).send("Internal Server Error");
    }
});



  app.get("/logout", (req, res) => {
	try {
		const username = req.session.username || "Unknown User";
	  // Log the user out by clearing the session
	  req.session.destroy(async (err) => {
		if (err) {
		  console.error("Error destroying session:", err);
		  await logLogoutActivity(username, false, "User logged out unsucessfully. Session not destroyed.");
		} else {
		  
		  console.log(`Session destroyed.`);
		  res.clearCookie('sessionToken');
		  // Log the logout activity using a separate async function
		  await logLogoutActivity(username, true, "User logged out. Session destroyed.");
		}
		// Redirect to the login page after logout
		res.redirect("/login");
	  });
	} catch (error) {
	  console.error("Error in logout route:", error);
	  res.status(500).send("Internal Server Error");
	}
  });
  

  app.get("/home", isAuthenticated, (req, res) => {
	  // Render the home page with sensor data
	  res.render("home", {
		username: req.session.username,
	  });
	});


  
app.get("/inusers", isAuthenticated, (req, res) => {
	// Fetch all user data from the database
	const allUsersQuery = "SELECT * FROM users";

	connection.query(allUsersQuery, (error, allUsers) => {
		if (error) {
			console.error("Error fetching all users:", error);
			res.status(500).send("Internal Server Error");
			return;
		}
		const currentUsername = req.session.username;
		// Render the inusers page with JSON data
		res.render("inusers", { allUsers ,csrfToken: csrfTokensession, currentUsername:currentUsername  });
	});
});
function isStrongPassword(password) {
	// Password must be at least 10 characters long
	if (password.length < 10) {
		return false;
	}

	// Password must contain at least one uppercase letter
	if (!/[A-Z]/.test(password)) {
		return false;
	}

	// Password must contain at least one lowercase letter
	if (!/[a-z]/.test(password)) {
		return false;
	}

	// Password must contain at least one digit
	if (!/\d/.test(password)) {
		return false;
	}

	// Password must contain at least one symbol
	if (!/[!@#$%^&*(),.?":{}|<>]/.test(password)) {
		return false;
	}

	return true;
}

const logUserCreationActivity = async (creatorUsername, success, message) => {
	try {
		const activity = success
			? "successful user creation"
			: `unsuccessful user creation: ${message}`;
		const logSql =
			"INSERT INTO user_logs (username, activity, timestamp) VALUES (?, ?, CURRENT_TIMESTAMP)";
		const logParams = [creatorUsername, activity];

		connection.query(logSql, logParams, (error, results) => {
			if (error) {
				console.error("Error logging user creation activity:", error);
				// Handle error (you may want to log it or take other appropriate actions)
			} else {
				console.log("User creation activity logged successfully");
			}

		});
	} catch (error) {
		console.error("Error in logUserCreationActivity function:", error);
		// Handle error (you may want to log it or take other appropriate actions)
	}
};

app.post(
    '/createUser',
    [
        body('name').trim().isLength({ min: 1 }).withMessage('Name must not be empty').escape(),
        body('username').trim().isLength({ min: 1 }).withMessage('Username must not be empty').escape(),
        body('email').isEmail().withMessage('Invalid email address').normalizeEmail(),
        body('password').custom((value) => {
            if (!isStrongPassword(value)) { throw new Error('Password does not meet complexity requirements'); } return true;
        }),
        body('jobTitle').trim().isLength({ min: 1 }).withMessage('Job title must not be empty').escape(),
    ],
    async (req, res) => {
        try {
            const errors = validationResult(req);

            if (!errors.isEmpty()) {
                return res.status(400).json({ errors: errors.array() });
            }

            // Validate the anti-CSRF token
            const submittedCSRFToken = req.body.csrf_token;

            if (!csrfTokensession || submittedCSRFToken !== csrfTokensession) {
                return res.status(403).json({ error: 'CSRF token mismatch' });
            }

            // Extract user input
            const { name, username, email, password, jobTitle } = req.body;
            console.log(submittedCSRFToken);
            // Extract the username of the user creating a new user
            const creatorUsername = req.session.username; // Adjust this based on how you store the creator's username in your session

            // Additional password complexity check
            if (!isStrongPassword(password)) {
                return res.status(400).json({ error: "Password does not meet complexity requirements" });
            }

            // Check if the username is already taken
            const checkUsernameQuery = "SELECT * FROM users WHERE username = ?";
            connection.query(checkUsernameQuery, [username], (usernameQueryErr, usernameResults) => {
                if (usernameQueryErr) {
                    console.error("Error checking username:", usernameQueryErr);
                    return res.status(500).json({ error: "Internal Server Error" });
                }

                if (usernameResults.length > 0) {
                    // Log unsuccessful user creation due to username taken
                    logUserCreationActivity(creatorUsername, false, "username taken");
                    return res.status(400).json({
                        error: "Username is already taken",
                        message: "Username is already taken. Please choose a different username."
                    });
                }

                // Check if the email is already taken
                const checkEmailQuery = "SELECT * FROM users WHERE email = ?";
                connection.query(checkEmailQuery, [email], (emailQueryErr, emailResults) => {
                    if (emailQueryErr) {
                        console.error("Error checking email:", emailQueryErr);
                        return res.status(500).json({ error: "Internal Server Error" });
                    }

                    if (emailResults.length > 0) {
                        // Log unsuccessful user creation due to email taken
                        logUserCreationActivity(creatorUsername, false, "email taken");
                        return res.status(400).json({
                            error: "Email is already in use",
                            message: "Email is already in use. Please choose another email."
                        });
                    }
					bcrypt.genSalt(10, (saltError, salt) => {
						if (saltError) {
							console.error("Error generating salt:", saltError);
							return res.status(500).json({ error: "Internal Server Error" });
						}
		
						bcrypt.hash(req.body.password, salt, (hashError, hashedPassword) => {
							if (hashError) {
								console.error("Error hashing password:", hashError);
								return res.status(500).json({ error: "Internal Server Error" });
							}
		
							connection.beginTransaction((transactionErr) => {
								if (transactionErr) {
									console.error("Error starting transaction:", transactionErr);
									return res.status(500).json({ error: "Internal Server Error" });
								}

                            // Define the insert query
                            const insertUserQuery =
                                "INSERT INTO users (name, username, email, password, lastLogin, jobTitle) VALUES (?, ?, ?, ?, NULL, ?)";

                            // Log the query and its parameters
                            console.log("Insert Query:", insertUserQuery);
                            console.log("Query Parameters:", [name, username, email, hashedPassword, jobTitle]);

                            // Execute the query with user data
                            connection.query(insertUserQuery, [name, username, email, hashedPassword, jobTitle], (queryErr, results) => {
                                if (queryErr) {
                                    console.error("Error executing query:", queryErr);

                                    // Rollback the transaction in case of an error
                                    connection.rollback((rollbackErr) => {
                                        if (rollbackErr) {
                                            console.error("Error rolling back transaction:", rollbackErr);
                                        }
                                        // Log unsuccessful user creation due to an error
                                        logUserCreationActivity(creatorUsername, false, "internal error");
                                        return res.status(500).json({ error: "Internal Server Error" });
                                    });
                                    return;
                                }

                                // Commit the transaction
                                connection.commit((commitErr) => {
									if (commitErr) {
										console.error("Error committing transaction:", commitErr);
										return res.status(500).json({ error: "Internal Server Error" });
									}
		
									res.status(200).json({ message: "User created successfully" });
									logUserCreationActivity(creatorUsername, true, "user created successfully");

                                    
								});
							});
						});
					});
				});
			});
		});
				} catch (error) {
					console.error("Error creating user:", error);
					return res.status(500).json({ error: "Internal Server Error" });
				}
			}
		);


app.get("/forgot-password", (req, res) => {
	res.render("forgot-password", { error: null, success: null });
});

// Handle the submission of the forgot password form
app.post("/forgot-password", (req, res) => {
	const { usernameOrEmail } = req.body;
  
	// Sanitize the input
	const sanitizedUsernameOrEmail = validator.escape(usernameOrEmail);
  
	// Perform the logic for sending the reset password email
  
	// Check if the username or email exists in the database
	const checkUserQuery = "SELECT * FROM users WHERE username = ? OR email = ?";
	connection.query(
	  checkUserQuery,
	  [sanitizedUsernameOrEmail, sanitizedUsernameOrEmail],
	  (checkError, checkResults) => {
		if (checkError) {
		  console.error("Error checking user:", checkError);
		  const error = "An error occurred during the password reset process.";
		  res.render("forgot-password", { error, success: null });
		} else if (checkResults.length === 0) {
		  const error = "Username or email not found.";
		  res.render("forgot-password", { error, success: null });
		} else {
		  // Assuming the user exists, generate a reset token and send an email
		  const user = checkResults[0];
		  const resetToken = crypto.randomBytes(20).toString("hex");
		  const resetTokenExpiry = new Date(Date.now() + 3600000); // Token expires in 1 hour
  
		  // Update user with reset token and expiry
		  const updateQuery =
			"UPDATE users SET reset_token = ?, reset_token_expiry = ? WHERE id = ?";
		  connection.query(
			updateQuery,
			[resetToken, resetTokenExpiry, user.id],
			(updateError) => {
			  if (updateError) {
				console.error("Error updating reset token:", updateError);
				const error =
				  "An error occurred during the password reset process.";
				res.render("forgot-password", { error, success: null });
			  } else {
				// Send email with reset link
				const resetLink = `http://localhost:3000/reset-password/${resetToken}`;
				const mailOptions = {
				  to: user.email,
				  subject: "Password Reset",
				  text: `Click on the following link to reset your password: ${resetLink}`,
				};
				transporter.sendMail(mailOptions, (emailError, info) => {
				  if (emailError) {
					console.error("Error sending email:", emailError);
					const error =
					  "An error occurred during the password reset process.";
					res.render("forgot-password", { error, success: null });
				  } else {
					console.log("Email sent: " + info.response);
					const success =
					  "Password reset email sent successfully. Check your inbox.";
					res.render("forgot-password", { error: null, success });
  
					// Log the successful sending of the reset link in the database
					logPasswordResetActivity(user.username,"link sent successfully");
				  }
				});
			  }
			}
		  );
		}
	  }
	);
  });

// Function to log the password reset activity in the database
function logPasswordResetActivity(username, activity) {
	const logSql =
		"INSERT INTO user_logs (username, activity, timestamp) VALUES (?, ?, CURRENT_TIMESTAMP)";
		connection.query(logSql, [username, activity], (error) => {
		if (error) {
			console.error("Error logging password reset activity:", error);
		} else {
			console.log("Password reset activity logged successfully");
		}
	});
}

// Handle Reset Password request
app.post("/reset-password/:token", async (req, res) => {
	const { token } = req.params;
	const { password, confirmPassword } = req.body;
  
	// Sanitize the inputs
	const sanitizedToken = validator.escape(token);
	const sanitizedPassword = validator.escape(password);
	const sanitizedConfirmPassword = validator.escape(confirmPassword);
  
	// Find user with matching reset token and not expired
	const selectQuery =
	  "SELECT * FROM users WHERE reset_token = ? AND reset_token_expiry > NOW()";
	connection.query(selectQuery, [sanitizedToken], async (selectErr, selectResults) => {
	  if (selectErr) {
		console.error("Error querying reset token:", selectErr);
		return res.status(500).json({ error: "Error querying reset token" });
	  }
  
	  if (selectResults.length === 0) {
		// Pass the error to the template when rendering the reset-password page
		return res.render("reset-password", {
		  token,
		  resetError: "Invalid or expired reset token",
		});
	  }
  
	  // Check if passwords match
	  if (sanitizedPassword !== sanitizedConfirmPassword) {
		// Pass the error to the template when rendering the reset-password page
		return res.render("reset-password", {
		  token,
		  resetError: "Passwords do not match",
		});
	  }
  
	  // Check if the new password meets complexity requirements
	  if (!isStrongPassword(sanitizedPassword)) {
		// Pass the error to the template when rendering the reset-password page
		return res.render("reset-password", {
		  token,
		  resetError:
			"Password does not meet complexity requirements. It must be at least 10 characters long and include at least one uppercase letter, one lowercase letter, one digit, and one symbol.",
		});
	  }
  
	  // Hash the new password
	  const hashedPassword = await new Promise((resolve, reject) => {
		bcrypt.genSalt(10, (saltError, salt) => {
			if (saltError) {
				console.error("Error generating salt:", saltError);
				reject("Internal Server Error");
			}
	
			// Use the generated salt to hash the password
			bcrypt.hash(sanitizedPassword, salt, (hashError, hashed) => {
				if (hashError) {
					console.error("Error hashing password:", hashError);
					reject("Internal Server Error");
				}
	
				resolve(hashed);
			});
		});
	});
  
	  // Update user's password and clear reset token
	  const updateQuery =
    "UPDATE users SET password = ?, reset_token = NULL, reset_token_expiry = NULL WHERE reset_token = ?";
connection.query(updateQuery, [hashedPassword, sanitizedToken], async (updateErr, updateResults) => {
 if (updateErr) {
		  console.error("Error updating password:", updateErr);
		  // Pass the error to the template when rendering the reset-password page
		  res.render("reset-password", {
			token,
			resetError: "Error updating password",
		  });
		} else {
		  // Log password reset activity
		  const username = selectResults[0].username; // Assuming 'username' is the column name
		  const logQuery = "INSERT INTO user_logs (username, activity, timestamp) VALUES (?, 'Password Reseted successfully', NOW())";
		  connection.query(logQuery, [username], (logErr) => {
			if (logErr) {
			  console.error("Error logging password reset:", logErr);
			  // You might want to handle the logging error here
			}
		  });
		  // Redirect to the success page upon successful password reset
		  res.redirect("/success");
		}
	  });
	});
  });

app.get("/success", (req, res) => {
	res.render("success");
});

app.get("/reset-password/:token", (req, res) => {
	const { token } = req.params;
	const error = req.query.error || null; // Get error from query parameter
	// Assuming you have this line in your server code where you render the reset-password view
	res.render("reset-password", {
		token,
		passwordValidationError: null,
		resetError: null,
		success: null,
	});
});
app.post("/reset-password", async (req, res) => {
    const { username, password, confirmPassword, csrf_token } = req.body;
    const creatorUsername = req.session.username;
    const submittedCSRFToken = req.body.csrf_token;

    if (!csrfTokensession|| submittedCSRFToken !== csrfTokensession) {
        return res.status(403).json({ error: 'CSRF token mismatch' });
    }

    // Sanitize the inputs
    const sanitizedUsername = validator.escape(username);
    const sanitizedPassword = validator.escape(password);
    const sanitizedConfirmPassword = validator.escape(confirmPassword);

    // Check if passwords match
    if (sanitizedPassword !== sanitizedConfirmPassword) {
        return res.status(400).json({ error: "Passwords do not match" });
    }

    // Check if the new password meets complexity requirements
    if (!isStrongPassword(sanitizedPassword)) {
        return res.status(400).json({
            error:
                "Password does not meet complexity requirements. It must be at least 10 characters long and include at least one uppercase letter, one lowercase letter, one digit, and one symbol.",
        });
    }

    // Generate a random salt
    const saltRounds = 10; // You can adjust the number of rounds based on your security requirements
    const salt = await bcrypt.genSalt(saltRounds);

    // Hash the new password with the generated salt
    const hashedPassword = await bcrypt.hash(sanitizedPassword, salt);

    // Check if the user exists in the database before updating the password
    const userExists = await checkIfUserExists(sanitizedUsername);

    if (!userExists) {
        return res.status(404).json({ error: "User does not exist" });
    }

    // Update user's password based on the username
    const updateQuery = "UPDATE users SET password = ? WHERE username = ?";
    connection.query(updateQuery, [hashedPassword, sanitizedUsername], async (updateErr, updateResults) => {
        if (updateErr) {
            console.error("Error updating password:", updateErr);
            return res.status(500).json({ error: "Error updating password" });
        }

        // Check if the update affected any rows
        if (updateResults.affectedRows > 0) {
            // Log password reset activity
            const logQuery = "INSERT INTO user_logs (username, activity, timestamp) VALUES (?, ?, NOW())";
            const logActivity = `Password has been reset for ${sanitizedUsername}`;
            connection.query(logQuery, [creatorUsername, logActivity], (logErr) => {
                if (logErr) {
                    console.error("Error logging password reset:", logErr);
                    // You might want to handle the logging error here
                }

                // Password update successful
                return res.status(200).json({ success: "Password updated successfully" });
            });
        } else {
            return res.status(404).json({
                error: "User not found or password not updated.",
            });
        }
    });
});


async function checkIfUserExists(username) {
    return new Promise((resolve, reject) => {
        const query = "SELECT * FROM users WHERE username = ?";
        connection.query(query, [username], (err, results) => {
            if (err) {
                reject(err);
            } else {
                resolve(results.length > 0);
            }
        });
    });
}
app.get('/searchUser', (req, res) => {
	const { username } = req.query;
  
	// Sanitize the input
	const sanitizedUsername = validator.escape(username);
  
	const query = 'SELECT * FROM users WHERE username = ?';
  
	connection.query(query, [sanitizedUsername], (err, results) => {
	  if (err) {
		console.error('MySQL query error:', err);
		res.status(500).json({ success: false, error: 'Internal Server Error' });
	  } else if (results.length === 0) {
		// No user found with the given username
		res.status(404).json({ success: false, error: 'User not found' });
	  } else {
		res.json(results);
	  }
	});
  });

app.get('/api/users', (req, res) => {
	const query = 'SELECT * FROM users';
  
	connection.query(query, (err, results) => {
	  if (err) {
		console.error('MySQL query error:', err);
		res.status(500).json({ success: false, error: 'Internal Server Error' });
	  } else {
		res.json(results);
	  }
	});
  });
  
  // Route to search for a user by username
  app.get('/api/searchUser', (req, res) => {
	const { username } = req.query;
	const query = 'SELECT * FROM users WHERE username = ?';
  
	connection.query(query, [username], (err, results) => {
	  if (err) {
		console.error('MySQL query error:', err);
		res.status(500).json({ success: false, error: 'Internal Server Error' });
	  } else {
		res.json(results);
	  }
	});
  });
  
  app.delete('/api/deleteUser/:username', async (req, res) => {
	const { username } = req.params;
	const query = 'DELETE FROM users WHERE username = ?';
	const creatorUsername = req.session.username;
  
	try {
	  // Extract CSRF token from the request body
	  const { csrfToken } = req.body;
  console.log(csrfToken);
  console.log(csrfTokensession);
	  // Compare CSRF token with the one stored in the session
	  if (csrfToken !== csrfTokensession) {
		return res.status(403).json({ success: false, error: 'CSRF token mismatch' });
	  }
  
	  // Log deletion activity to USER_LOGS
	  const deletionActivity = `User ${username} has been successfully deleted`;
	  const logQuery = 'INSERT INTO USER_LOGS (USERNAME, ACTIVITY, TIMESTAMP) VALUES (?, ?, CURRENT_TIMESTAMP)';
	  await executeQuery(logQuery, [creatorUsername, deletionActivity]);
  
	  // Perform user deletion
	  const results = await executeQuery(query, [username]);
  
	  if (results.affectedRows === 0) {
		res.status(404).json({ success: false, error: 'User not found' });
	  } else {
		res.json({ success: true, message: 'User deleted successfully' });
	  }
	} catch (error) {
	  console.error('MySQL query error:', error);
	  res.status(500).json({ success: false, error: 'Internal Server Error', details: error.message });
	}
  });
  
  
  async function executeQuery(sql, values) {
	return new Promise((resolve, reject) => {
	  connection.query(sql, values, (err, results) => {
		if (err) {
		  reject(err);
		} else {
		  resolve(results);
		}
	  });
	});
  }
  
  app.get('/api/getLogs', (req, res) => {
	// Query the database to fetch logs
	const query = 'SELECT id, username, activity, timestamp FROM user_logs';
	connection.query(query, (err, results) => {
	  if (err) {
		console.error('Error fetching logs from MySQL:', err);
		res.status(500).json({ error: 'Error fetching logs from MySQL' });
		return;
	  }
  
	  // Format timestamps to a more readable format
	  const formattedLogs = results.map((log) => ({
		id: log.id,
		username: log.username,
		activity: log.activity,
		timestamp: new Date(log.timestamp).toLocaleString('en-US', { timeZone: 'Asia/Singapore' }),
	  }));
  
	  // Send the formatted logs as a JSON response
	  res.json(formattedLogs);
	});
  });
  

app.use(express.static("views"));

app.listen(PORT, () => {
	console.log(`Server is running on port ${PORT}`);
});
