spurrin-backend/src/controllers/appUserController.js
2025-07-31 23:13:17 +05:30

3361 lines
105 KiB
JavaScript

const bcrypt = require("bcrypt");
const db = require("../config/database"); // Database connection
const fs = require("fs");
const jwt = require("jsonwebtoken");
const nlp = require("compromise");
const nodemailer = require("nodemailer");
const sender_port = process.env.SENDER_PORT;
const sender_security = process.env.SENDER_SECURITY;
const path = require('path')
const { emitEvent } = require("../services/secondaryWebsocket");
console.log('sender port : ', sender_port);
console.log('sender security : ', sender_security);
// zoho transporter
const transporter = nodemailer.createTransport({
host: "smtp.zoho.com",
port: 465,
secure: true,
auth: {
user: "kavya.j@tech4biz.io", // Your Zoho email address
pass: "8pQfkBw8gbrz", // Your Zoho App Password (not your account password)
}
});
exports.initWebSocket = (io) => {
io.on("connection", (socket) => {
console.log("Hospital connected:", socket.id);
socket.on("register_hospital", (hospitalCode) => {
hospitalSockets[hospitalCode] = socket;
console.log(`Hospital ${hospitalCode} registered.`);
});
socket.on("disconnect", () => {
const hospitalCode = Object.keys(hospitalSockets).find(
(key) => hospitalSockets[key] === socket
);
if (hospitalCode) delete hospitalSockets[hospitalCode];
console.log(`Hospital ${hospitalCode} disconnected.`);
});
});
};
exports.uploadIdPhoto = async (req, res) => {
try {
// Extracting user ID and hospital code
const userId = parseInt(req.params.id, 10); // User ID from route
const { hospital_code } = req.user; // Authenticated user's hospital code
// Check if user ID is valid
if (isNaN(userId)) {
console.error("Invalid User ID:", userId);
return res.status(400).json({ error: "Invalid user ID" });
}
// Check if a file was uploaded
if (!req.file) {
console.error("No file uploaded");
return res.status(400).json({ error: "No file uploaded" });
}
const photoPath = `/uploads/id_photos/${req.file.filename}`;
// Verify app user is part of the same hospital
const query = `
SELECT hospital_code FROM app_users WHERE id = ? AND hospital_code = ?
`;
const result = await db.query(query, [userId, hospital_code]);
if (result.length === 0) {
console.error(
"Authorization failed for user ID:",
userId,
"with hospital_code:",
hospital_code
);
return res
.status(403)
.json({ error: "You are not authorized to upload ID for this user" });
}
// Update the ID photo path in the database
await db.query("UPDATE app_users SET id_photo_url = ? WHERE id = ?", [
photoPath,
userId,
]);
res.status(200).json({
message: "ID photo uploaded successfully!",
id_photo_url: photoPath,
});
} catch (error) {
console.error("Error uploading ID photo:", error.message);
res.status(500).json({ error: "Internal server error" });
}
};
exports.updateSettings = async (req, res) => {
try {
const userId = req.user.id; // Assuming user is authenticated and userId is available
const { pin, pin_enabled, remember_me } = req.body;
// Validate pin (if provided)
if (pin && (typeof pin !== 'string' || pin.length !== 4)) {
return res.status(400).json({ error: 'Invalid PIN format. Must be a 4-digit string.' });
}
// Determine expiry based on remember_me
let expiresIn = '5h';
let expiryTimestamp = new Date();
if (remember_me) {
expiresIn = '30d';
expiryTimestamp.setDate(expiryTimestamp.getDate() + 30);
} else {
expiryTimestamp.setHours(expiryTimestamp.getHours() + 5);
}
// Generate new access token
const payload = { id: userId, role: 'AppUser' };
const accessToken = jwt.sign(payload, process.env.JWT_ACCESS_TOKEN_SECRET, {
expiresIn: expiresIn,
});
// Update user settings and access token
const query = `UPDATE app_users SET pin_number = ?, pin_enabled = ?, remember_me = ?, access_token = ?, access_token_expiry = ? WHERE id = ?`;
const result=await db.query(query, [pin, pin_enabled, remember_me, accessToken, expiryTimestamp, userId]);
if (result.affectedRows > 0) {
console.log("Table updated successfully.");
} else {
console.log("Table not updated. No matching user found.");
}
res.status(200).json({ message: 'Settings updated successfully.', accessToken });
} catch (error) {
console.error('Error updating settings:', error);
res.status(500).json({ error: 'Internal Server Error' });
}
};
exports.hitlike = async (req, res) => {
try {
// Extract user ID and session ID from the request
const { session_id, id } = req.body;
const log_id = id;
const app_user_id = req.user.id;
// Check if both app_user_id and session_id are provided
if (!app_user_id || !session_id || !log_id) {
return res.status(400).json({
status: 'error',
message: 'app user id and session id and log id are required',
});
}
// Query to toggle the is_liked value
const toggleQuery = `
UPDATE interaction_logs
SET is_liked = NOT is_liked
WHERE app_user_id = ? AND session_id = ? AND id = ?
`;
// Execute the query
const result = await db.query(toggleQuery, [app_user_id, session_id,log_id]);
// Check if any rows were affected
if (result.affectedRows > 0) {
return res.status(200).json({
status: 'success',
message: 'Like updated successfully',
data: {
app_user_id,
session_id,
is_liked: result.changedRows > 0 ? 1 : 0, // 1 if changed, 0 if not
},
});
} else {
return res.status(404).json({
status: 'error',
message: 'No matching record found to toggle',
});
}
} catch (error) {
console.error('Error during like toggle:', error);
return res.status(500).json({
status: 'error',
message: 'Internal server error',
});
}
};
exports.hitFlag = async (req, res) => {
try {
// Extract user ID and session ID from the request
const { session_id, logid } = req.body;
const log_id = logid;
const app_user_id = req.user.id;
// Check if both app_user_id and session_id are provided
if (!app_user_id || !session_id || !log_id) {
return res.status(400).json({
status: 'error',
message: 'app user id and session id and log id are required',
});
}
// Query to toggle the is_liked value
const toggleQuery = `
UPDATE interaction_logs
SET is_flagged = NOT is_flagged
WHERE app_user_id = ? AND session_id = ? AND id = ?
`;
// Execute the query
const result = await db.query(toggleQuery, [app_user_id, session_id,log_id]);
// Check if any rows were affected
if (result.affectedRows > 0) {
return res.status(200).json({
status: 'success',
message: 'Updated successfully',
data: {
app_user_id,
session_id
},
});
} else {
return res.status(404).json({
status: 'error',
message: 'No matching record found to toggle',
});
}
} catch (error) {
console.error('Error during like toggle:', error);
return res.status(500).json({
status: 'error',
message: 'Internal server error',
});
}
};
exports.addReportText = async (req, res) => {
try {
const { session_id, report_text } = req.body;
const app_user_id = req.user.id;
// Validate input
if (!app_user_id || !session_id || typeof report_text !== 'string') {
return res.status(400).json({
status: 'error',
message: 'app_user_id, session_id, logid, and report_text are required',
});
}
// Update query
const updateQuery = `
UPDATE interaction_logs
SET report_text = ?
WHERE app_user_id = ? AND session_id = ?
`;
// Execute update
const result = await db.query(updateQuery, [report_text, app_user_id, session_id]);
// Handle response
if (result.affectedRows > 0) {
return res.status(200).json({
status: 'success',
message: 'Session reported successfully. Admin will review your report',
data: {
app_user_id,
session_id,
report_text
},
});
} else {
return res.status(404).json({
status: 'error',
message: 'No matching record found to update report text',
});
}
} catch (error) {
console.error('Error updating report text:', error);
return res.status(500).json({
status: 'error',
message: 'Internal server error',
});
}
};
exports.updateChecked = async (req,res) =>{
try {
const app_user_id = req.params.id;
if (!["Admin", 8].includes(req.user.role)) {
return res.status(403).json({ error: "Unauthorized to approve IDs" });
}
const updateQuery = `
UPDATE app_users
SET checked = ?
WHERE id = ?
`;
const result = await db.query(updateQuery, [1, app_user_id]);
if (result.affectedRows > 0) {
return res.status(200).json({
status: 'success',
message: 'Acknowledged successfully',
});
} else {
return res.status(404).json({
status: 'error',
message: 'No matching record found to update checked',
});
}
} catch (error) {
console.error("Error updating checked:", error);
return res.status(500).json({ error: "Internal server error" });
}
}
exports.signup = async (req, res) => {
try {
const { pin, pin_status,remember_me, email, password, hospital_code, username } = req.body;
if (!email || !password || !hospital_code || !username) {
return res.status(400).json({
error: "Email, password, username, and hospital code are required",
});
}
const pin_enabled = (pin_status === undefined || pin_status === '') ? 0 : pin_status;
const remember_me_ = (remember_me === undefined || remember_me === '') ? 0 : remember_me;
// Check if the hospital_code exists in the `hospitals` table
const hospitalQuery =
"SELECT hospital_code FROM hospitals WHERE hospital_code = ?";
const hospitalResult = await db.query(hospitalQuery, [hospital_code]);
if (hospitalResult.length === 0) {
return res.status(404).json({ error: "Invalid hospital code" });
}
// Check if the email is already in use
const userQuery = "SELECT id FROM app_users WHERE email = ?";
const userResult = await db.query(userQuery, [email]);
if (userResult.length > 0) {
return res.status(400).json({ error: "Email already in use" });
}
// Check if a file was uploaded
if (!req.file) {
return res.status(400).json({ error: "ID photo url is required" });
}
// Hash the password
const hashPassword = await bcrypt.hash(password, 10);
// Insert the new app user into the `app_users` table
const insertQuery = `
INSERT INTO app_users (email, hash_password, hospital_code, status, username, pin_number, pin_enabled, remember_me )
VALUES (?, ?, ?, 'Pending', ?, ?, ?,?)
`;
const result = await db.query(insertQuery, [
email,
hashPassword,
hospital_code,
username,
pin, // Set pin to null if not provided
pin_enabled,
remember_me_
]);
const userId = result.insertId; // Get the new user's ID
const filePath = `/uploads/id_photos/${req.file.filename}`; // Correct file path
// Update the ID photo path in the database
await db.query(
"UPDATE app_users SET id_photo_url = ?, upload_status = ? WHERE id = ?",
[filePath, "1", userId]
);
// ✅ Notify hospitals in the SECONDARY WebSocket instance
emitEvent("new_user", {
message: `A new user has been created for hospital ${hospital_code}.`,
user: { id: userId, username, email, hospital_code: hospital_code },
});
res.status(201).json({
message: "User signed up and ID photo uploaded successfully!",
data: {
id: userId,
email,
hospital_code,
username,
id_photo_url: filePath,
pin: pin || null,
pin_status : pin_status,
remember_me: remember_me
},
});
} catch (error) {
console.error("Error during signup and ID photo upload:", error.message);
res.status(500).json({ error: "Internal server error" });
}
};
exports.login = async (req, res) => {
try {
const { email, password } = req.body;
let remember_me;
if (!email || !password) {
return res.status(400).json({ error: "Email and password are required" });
}
console.log("email----",email)
// Check if the user exists
const query = "SELECT * FROM app_users WHERE email = ?";
const result = await db.query(query, [email]);
console.log("result---",result)
if (result.length === 0) {
return res.status(404).json({ error: "User not found" });
}
const user = result[0];
remember_me = user.remember_me
console.log("user-data----------------------",user);
const hospitalData = await db.query("SELECT * FROM hospitals WHERE hospital_code = ?", [user.hospital_code]);
// if (hospitalData.publicSignupEnabled) {
// throw new Error("Hospital not found");
// }
console.log("hospitalData---",hospitalData)
let actual_status;
actual_status = user.status
if(hospitalData[0].publicSignupEnabled){
user.status = "Active"
}
if (user.status === "Pending" && !hospitalData[0].publicSignupEnabled) {
return res.status(404).json({ error: "Your Account is Under Review" });
}
if (user.status === "Inactive" && !hospitalData[0].publicSignupEnabled) {
return res.status(404).json({ error: "Contact admin your account is not approved" });
}
// Validate the password
const validPassword = await bcrypt.compare(password, user.hash_password);
if (!validPassword) {
return res.status(401).json({ error: "Invalid email or password" });
}
// Determine expiry based on remember_me
let expiresIn = "5h";
let expiryTimestamp = new Date();
let rememberMeValue = remember_me;
if (rememberMeValue === undefined) rememberMeValue = user.remember_me;
if (rememberMeValue === true || rememberMeValue === 1 || rememberMeValue === "1" || rememberMeValue === "true") {
const updateQuery = `
UPDATE app_users
SET remember_me = ?
WHERE id = ?
`;
await db.query(updateQuery, [remember_me,user.id]);
expiresIn = "30d";
expiryTimestamp.setDate(expiryTimestamp.getDate() + 30);
} else {
expiryTimestamp.setHours(expiryTimestamp.getHours() + 5);
}
// Generate a new access token
const payload = { id: user.id, email: user.email, role: "AppUser" };
const accessToken = jwt.sign(payload, process.env.JWT_ACCESS_TOKEN_SECRET, {
expiresIn: expiresIn,
});
// SQL query to fetch hospital data based on the provided hospital_code
const query_hospital = `
SELECT * FROM hospitals WHERE hospital_code = ?;
`;
// Run the query
const result_hospital = await db.query(query_hospital, [user.hospital_code]);
// hospital users
const queryHospitalUsr = `
SELECT * FROM hospital_users WHERE hospital_code = ?;
`;
// Run the query
const resultHospitalUsr = await db.query(queryHospitalUsr, [user.hospital_code]);
const hospitalUser = resultHospitalUsr[0];
if (!hospitalUser) {
return res.status(404).json({ error: "Hospital user not found" });
}
// Update the access token and expiry in the database
const updateQuery = `
UPDATE app_users
SET access_token = ?, access_token_expiry = ?, remember_me = ?
WHERE id = ?
`;
await db.query(updateQuery, [accessToken, expiryTimestamp, (rememberMeValue === true || rememberMeValue === 1 || rememberMeValue === "1" || rememberMeValue === "true") ? 1 : 0, user.id]);
// Send response
res.status(200).json({
message: "Login successful",
user: {
id: user.id,
email: user.email,
pin: user.pin_number,
pin_enabled: user.pin_enabled,
hospital_code: user.hospital_code,
hospital_id : hospitalData[0].id,
status: user.status,
actualStatus: actual_status,
hospital_name: result_hospital[0].name_hospital,
primary_color: result_hospital[0].primary_color,
secondary_color: result_hospital[0].secondary_color,
upload_status: user.upload_status,
id_photo_url: user.id_photo_url,
primary_admin_email: result_hospital[0].primary_admin_email,
mobile_number: result_hospital[0].mobile_number,
username: user.username,
logo_url: resultHospitalUsr[0].profile_photo_url,
query_title: user.query_title,
remember_me: (rememberMeValue === true || rememberMeValue === 1 || rememberMeValue === "1" || rememberMeValue === "true") ? 1 : 0
},
accessToken,
});
} catch (error) {
console.error("Error during login:", error.message);
res.status(500).json({ error: "Internal server error" });
}
};
exports.checkPin = async (req, res) => {
try {
const { email, pin } = req.body;
if (!email || !pin) {
return res.status(400).json({ error: "Email and Pin are required" });
}
// Check if the user exists
const query = "SELECT * FROM app_users WHERE email = ?";
const result = await db.query(query, [email]);
if (result.length === 0) {
return res.status(404).json({ error: "User not found" });
}
const user = result[0];
const hospitalData = await db.query("SELECT * FROM hospitals WHERE hospital_code = ?", [user.hospital_code]);
if (user.status === "Pending" && !hospitalData[0].publicSignupEnabled) {
throw new Error("Your Account is Under Review");
}
if (user.status === "Inactive" && !hospitalData[0].publicSignupEnabled) {
throw new Error("Contact admin your account is not approved");
}
// Check PIN if PIN status is enabled
if (pin !== user.pin_number) {
return res.status(401).json({
error: "Invalid PIN",
requires_pin: true,
message: "Incorrect PIN. Please try again"
});
}
// Send response
res.status(200).json({
message: "Pin verified successfully",
});
} catch (error) {
console.error("Error during login:", error.message);
res.status(500).json({ error: "Internal server error" });
}
};
exports.logout = async (req, res) => {
try {
const userId = req.user.id; // Assuming the user is authenticated via middleware
// Check if the user exists
const query = "SELECT * FROM app_users WHERE id = ?";
const result = await db.query(query, [userId]);
if (result.length === 0) {
return res.status(404).json({ error: "User not found" });
}
// Invalidate the access token in the database
const updateQuery = `
UPDATE app_users
SET access_token = NULL, access_token_expiry = NULL
WHERE id = ?
`;
await db.query(updateQuery, [userId]);
res.status(200).json({ message: "Logout successful" });
} catch (error) {
console.error("Error during logout:", error.message);
res.status(500).json({ error: "Internal server error" });
}
};
// controller.js
exports.getAppUsersByHospitalCode = async (req, res) => {
try {
// Extract the hospital_code from the token (req.user object)
const userId = req.user.id;
if (!userId) {
return res.status(400).json({ error: "User not found for the token" });
}
// Query to fetch hospital users based on the hospital_code
const query = `
SELECT id, email, status,hospital_code
FROM app_users
WHERE id = ?;
`;
const result = await db.query(query, [userId]);
if (result.length === 0) {
return res
.status(404)
.json({ error: "No users found for the specified Token" });
}
const hospitalData = await db.query("SELECT * FROM hospitals WHERE hospital_code = ?", [result[0].hospital_code]);
if(hospitalData[0].publicSignupEnabled){
result[0].status = 'Active'
}
// Send the response with the users data
res.status(200).json({
message: "Hospital users fetched successfully",
user: result[0],
});
} catch (error) {
console.error("Error fetching hospital users:", error.message);
res.status(500).json({ error: "Internal server error" });
}
};
exports.approveUserId = async (req, res) => {
try {
const appUserId = req.params.id; // App user ID to approve
const { role } = req.user; // Authenticated user's details
const { Action } = req.body;
const { hospital_code } = req.user;
if (!req.body.Action) {
return res.status(400).json({ error: "Action is required" });
}
if (!["Superadmin", "Admin", 8].includes(role)) {
return res.status(403).json({ error: "Unauthorized to approve IDs" });
}
const query = `
SELECT hospital_code FROM app_users WHERE id = ? AND hospital_code = ?
`;
const result = await db.query(query, [appUserId, hospital_code]);
if (result.length === 0) {
return res
.status(403)
.json({ error: "User does not belong to your hospital" });
}
// Approve the ID
if (Action == "Reject") {
await db.query('UPDATE app_users SET status = "Inactive" WHERE id = ?', [
appUserId,
]);
res.status(200).json({ message: "ID Rejected successfully" });
} else if (Action == "Approve") {
await db.query('UPDATE app_users SET status = "Active" WHERE id = ?', [
appUserId,
]);
res.status(200).json({ message: "ID approved successfully" });
}
} catch (error) {
console.error("Error approving ID:", error.message);
res.status(500).json({ error: "Internal server error" });
}
};
exports.getAppUsers = async (req, res) => {
try {
const { role } = req.user;
// Ensure the user has the proper role
if (!["Superadmin", "Admin", 9, 8].includes(role)) {
return res.status(403).json({ error: "Unauthorized to view app users" });
}
// Query to fetch app users
const query = `
SELECT * FROM app_users;
`;
const users = await db.query(query);
if (users.length === 0) {
return res
.status(404)
.json({ message: "No app users found for this hospital" });
}
res.status(200).json({
message: "App users fetched successfully",
data: users,
});
} catch (error) {
console.error("Error fetching app users:", error.message);
res.status(500).json({ error: "Internal server error" });
}
};
exports.getAppUserByHospitalId = async (req, res) => {
try {
const { role } = req.user;
const { id } = req.params; // Extract user ID from request parameters
// Log authenticated user details
// Ensure the user has the proper role
if (!["Superadmin", "Admin", 8, 9].includes(role)) {
return res.status(403).json({ error: "Unauthorized to view app users" });
}
// fetching hospital code from hospital id
const query1 = `SELECT * FROM hospitals WHERE id = ?`;
const result1 = await db.query(query1, [id]);
const hospital_code = result1[0].hospital_code;
console.log("result1----", result1);
// Query to fetch the app user by hospital_code
const query = `SELECT * FROM app_users WHERE hospital_code = ?`;
const users = await db.query(query, [hospital_code]);
if (users.length === 0) {
return res.status(404).json({ message: "App users not found" });
}
res.status(200).json({
message: "App user fetched successfully",
data: users, // Return single user object
});
} catch (error) {
console.error("Error fetching app user:", error.message);
res.status(500).json({ error: "Internal server error" });
}
};
exports.deleteAppUser = async (req, res) => {
try {
const { id } = req.params;
const { hospital_code } = req.user;
// Check if the user exists
const appUserquery = "SELECT * FROM app_users WHERE id = ?";
const users = await db.query(appUserquery, [id]);
if (users.length === 0) {
return res
.status(404)
.json({ message: "No app users found for this hospital" });
}
// Ensure only Admin or Superadmin can delete users
if (!["Admin", "Superadmin", 8, 7,"AppUser"].includes(req.user.role)) {
return res.status(403).json({ error: "Unauthorized to delete users" });
}
// Ensure user belongs to the same hospital
const query =
"SELECT hospital_code,id_photo_url FROM app_users WHERE id = ? AND hospital_code = ?";
const result = await db.query(query, [id, hospital_code]);
if (!result || result.length === 0) {
return res
.status(403)
.json({ error: "User does not belong to your hospital" });
}
// Unlink (delete) the associated file if it exists and is not null
if (result[0].id_photo_url) {
const filePath = path.join(__dirname, '..','..', 'uploads', result[0].id_photo_url.replace(/^\/uploads\//, ''));
fs.access(filePath, fs.constants.F_OK, (err) => {
if (err) {
console.error(`File not found: ${filePath}`);
return;
}
fs.unlink(filePath, (err) => {
if (err) {
console.error('Error deleting file:', err.message);
} else {
console.log('File deleted successfully:', filePath);
}
});
});
} else {
console.log('No file to delete - id_photo_url is null');
}
// delete feedback
await db.query(
'DELETE FROM feedback WHERE sender_type = ? AND sender_id = ?',
['appuser', id] // Fixed: should be 'id' not 'req.user.id'
);
// Delete the user
const deleteResult = await db.query("DELETE FROM app_users WHERE id = ?", [
id,
]);
if (deleteResult.affectedRows === 0) {
return res.status(404).json({ error: "User not found" });
}
res.status(200).json({ message: "User deleted successfully" });
} catch (error) {
console.error("Error deleting user:", error.message);
res.status(500).json({ error: "Internal server error" });
}
};
// query title CRUD
exports.updateQueryTitle = async (req, res) => {
const id = req.user.id;
const { query_title } = req.body;
if (!query_title) {
return res.status(400).json({ error: "query_title is required" });
}
try {
const result = await db.query(
"UPDATE app_users SET query_title = ? WHERE id = ?",
[query_title, id]
);
if (result.affectedRows === 0) {
return res.status(404).json({ error: "User not found" });
}
res.json({ message: "Query title updated successfully" });
} catch (error) {
console.error("Error updating query title:", error);
res.status(500).json({ error: "Internal server error" });
}
};
// Delete query_title for a user by user ID
exports.getShortTitle = (req, res) => {
const { question } = req.body;
console.log("Question: ", question);
if (!question) return res.status(400).json({ error: "No question provided" });
let shortTitle = nlp(question).sentences().toTitleCase().out("text");
// Remove unnecessary question words
shortTitle = shortTitle
.replace(
/^(What|How|Why|When|Where|Which|Who|Is|Are|Do|Does|Can|Could)\s+/i,
""
)
.trim();
if (!shortTitle)
return res.status(400).json({ error: "Invalid question format" });
console.log("short question:", shortTitle);
res.json({ query_title: shortTitle });
};
exports.deleteQueryTitle = async (req, res) => {
const id = req.user.id;
try {
const result = await db.query(
"UPDATE app_users SET query_title = NULL WHERE id = ?",
[id]
);
if (result.affectedRows === 0) {
return res.status(404).json({ error: "User not found" });
}
res.json({ message: "Query title deleted successfully" });
} catch (error) {
console.error("Error deleting query title:", error);
res.status(500).json({ error: "Internal server error" });
}
};
exports.sendOtp = async (req, res) => {
try {
const { email } = req.body;
// Validate email input
if (!email) {
return res.status(400).json({ error: "Email is required" });
}
// Check if user exists
const user = await db.query(
"SELECT id, username, hospital_code FROM app_users WHERE email = ?",
[email]
);
if (!user.length) {
return res.status(404).json({ error: "User not found" });
}
console.log("user", user);
const userId = user[0].id;
const hospital_code = user[0].hospital_code;
// fetch hospital name of app_user
const hospital = await db.query(
"SELECT name_hospital FROM hospitals WHERE hospital_code = ?",
[hospital_code]
);
console.log("hospital result : ", hospital[0].name_hospital);
// Generate a 6-digit OTP
const otp = Math.floor(100000 + Math.random() * 900000).toString();
const expiresAt = new Date(Date.now() + 2 * 60 * 60 * 1000); // OTP expires in 1 hour
console.log("otp : ", otp, "expiresAt: ", expiresAt);
// Store OTP in database
await db.query(
"UPDATE app_users SET otp_code = ?, otp_expires_at = ? WHERE id = ?",
[otp, expiresAt, userId]
);
// // Send OTP via email
const info = await sendMail(
email,
hospital[0].name_hospital,
user[0].username,
otp
);
res.json({ message: "OTP sent successfully", email_status: info.response });
} catch (error) {
console.error("Error sending OTP:", error);
res.status(500).json({ error: "Internal server error" });
}
};
exports.changePassword = async (req, res) => {
try {
const { email, otp, new_password } = req.body;
console.log("email : ", email);
// Validate inputs
if (!email || !otp || !new_password) {
return res
.status(400)
.json({ error: "Email, OTP, and new password are required" });
}
// Fetch OTP from the database
const user = await db.query(
"SELECT id, otp_code, otp_expires_at FROM app_users WHERE email = ?",
[email]
);
if (!user.length) {
return res.status(404).json({ error: "User not found" });
}
const userData = user[0];
// ✅ Check if OTP matches
if (userData.otp_code !== otp) {
return res.status(400).json({ error: "Invalid OTP" });
}
// ✅ Check if OTP is expired
if (new Date() > new Date(userData.otp_expires_at)) {
return res.status(400).json({ error: "OTP expired. Request a new one." });
}
// ✅ Hash the new password
const hashedPassword = await bcrypt.hash(new_password, 10);
// ✅ Update password in DB & clear OTP
await db.query(
"UPDATE app_users SET hash_password = ?, otp_code = NULL, otp_expires_at = NULL WHERE id = ?",
[hashedPassword, userData.id]
);
res.json({ message: "Password changed successfully!" });
} catch (error) {
console.error("Error resetting password:", error);
res.status(500).json({ error: "Internal server error" });
}
};
exports.sendPinOtp = async (req, res) => {
try {
const { email } = req.body;
// Validate email input
if (!email) {
return res.status(400).json({ error: "Email is required" });
}
// Check if user exists
const user = await db.query(
"SELECT id, username, hospital_code FROM app_users WHERE email = ?",
[email]
);
if (!user.length) {
return res.status(404).json({ error: "User not found" });
}
console.log("user", user);
const userId = user[0].id;
const hospital_code = user[0].hospital_code;
// fetch hospital name of app_user
const hospital = await db.query(
"SELECT name_hospital FROM hospitals WHERE hospital_code = ?",
[hospital_code]
);
console.log("hospital result : ", hospital[0].name_hospital);
// Generate a 6-digit OTP
const otp = Math.floor(100000 + Math.random() * 900000).toString();
const expiresAt = new Date(Date.now() + 2 * 60 * 60 * 1000); // OTP expires in 1 hour
console.log("otp : ", otp, "expiresAt: ", expiresAt);
// Store OTP in database
await db.query(
"UPDATE app_users SET pin_otp = ?, pin_otp_expiry = ? WHERE id = ?",
[otp, expiresAt, userId]
);
// // Send OTP via email
const info = await sendMail(
email,
hospital[0].name_hospital,
user[0].username,
otp
);
res.json({ message: "OTP sent successfully", email_status: info.response });
} catch (error) {
console.error("Error sending OTP:", error);
res.status(500).json({ error: "Internal server error" });
}
};
exports.changePinByOtp = async (req, res) => {
try {
const { email, otp, new_pin } = req.body;
console.log("email : ", email);
// Validate inputs
if (!email || !otp || !new_pin) {
return res
.status(400)
.json({ error: "Email, OTP, and new pin are required" });
}
// Fetch OTP from the database
const user = await db.query(
"SELECT id, pin_otp, pin_otp_expiry FROM app_users WHERE email = ?",
[email]
);
if (!user.length) {
return res.status(404).json({ error: "User not found" });
}
const userData = user[0];
// ✅ Check if OTP matches
if (userData.pin_otp !== otp) {
return res.status(400).json({ error: "Invalid OTP" });
}
// ✅ Check if OTP is expired
if (new Date() > new Date(userData.otp_expires_at)) {
return res.status(400).json({ error: "OTP expired. Request a new one." });
}
// ✅ Hash the new password
// ✅ Update password in DB & clear OTP
await db.query(
"UPDATE app_users SET pin_number = ?, pin_otp = NULL, pin_otp_expiry = NULL WHERE id = ?",
[new_pin, userData.id]
);
res.json({ message: "Pin changed successfully!" });
} catch (error) {
console.error("Error resetting pin:", error);
res.status(500).json({ error: "Internal server error" });
}
};
async function sendMail(email, hospital_name, username, otp) {
const mailOptions = {
from: "kavya.j@tech4biz.io", // Sender's email
to: email, // Recipient's email
subject: "Spurrinai Login Credentials", // Email subject
html: `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Reset Your Password or Pin - Spurrinai Medical Platform</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Syne:wght@400..800&display=swap');
body {
font-family: 'Inter', sans-serif;
margin: 0;
padding: 0;
background-color: #ebf3fa;
color: #333;
}
.email-container {
max-width: 600px;
margin: 20px auto;
background: white;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
}
.email-header {
background: linear-gradient(135deg, #2193b0, #6dd5ed);
padding: 30px;
text-align: center;
color: white;
}
.hospital-name {
display: inline-block;
background-color: rgba(255, 255, 255, 0.2);
padding: 5px 15px;
border-radius: 20px;
font-size: 14px;
margin-bottom: 10px;
}
.email-header h1 {
margin: 10px 0 0;
font-size: 26px;
font-weight: 500;
}
.email-content {
padding: 40px 30px;
}
.greeting {
font-size: 30px;
font-weight: 700;
margin-bottom: 20px;
color: #303030;
}
.greeting-text{
font-size: 18px;
font-weight: 400;
margin-bottom: 20px;
line-height: 1.7;
color: #303030;
}
.verification-code {
background-color: #f5f9fc;
border: 1px solid #e0e9f0;
border-radius: 8px;
padding: 20px;
margin: 25px 0;
text-align: center;
}
.code {
font-family: 'Courier New', monospace;
font-size: 32px;
letter-spacing: 6px;
color: #2193b0;
font-weight: bold;
padding: 10px 0;
}
.reset-button {
display: block;
background-color: #2193b0;
color: white;
text-decoration: none;
text-align: center;
padding: 15px 20px;
border-radius: 5px;
margin: 30px auto;
max-width: 250px;
font-weight: 500;
transition: background-color 0.3s;
}
.reset-button:hover {
background-color: #1a7b92;
}
.expiry-note {
background-color: #fff8e1;
border-left: 4px solid #ffc107;
padding: 12px 15px;
margin: 25px 0;
font-size: 14px;
color: #856404;
}
.security-note {
margin-top: 30px;
padding-top: 20px;
border-top: 1px solid #eee;
font-size: 14px;
color: #666;
}
.email-footer {
background-color: #f5f9fc;
padding: 20px;
text-align: center;
font-size: 13px;
color: #888;
border-top: 1px solid #e0e9f0;
}
.support-link {
color: #2193b0;
text-decoration: none;
}
.device-info {
margin-top: 20px;
background-color: #f5f9fc;
padding: 15px;
border-radius: 6px;
font-size: 14px;
}
.device-info p {
margin: 5px 0;
color: #666;
}
</style>
</head>
<body>
<div class="email-container">
<div class="email-header">
<div class="hospital-name"> ${hospital_name}</div>
<h1>Reset Your Password or Pin</h1>
</div>
<div class="email-content">
<div class="greeting">Hello ${username},</div>
<p class="greeting-text" >We received a request to <strong>reset the password</strong> for your account on the <strong> Spurrinai healthcare platform</strong>. For your security reasons, please verify this action.</p>
<div class="verification-code">
<p>Please enter this verification code:</p>
<div class="code">${otp}</div>
<p>on the password reset screen</p>
</div>
<a href="spurrinai://ResetPassword/${otp}" class="reset-button">Reset Password</a>
<div class="expiry-note">
<strong>Note:</strong> This verification code will expire in 2 hours for security reasons.
</div>
<div class="security-note">
<p>If you did not request this password reset, please contact our IT security team immediately at <a href="mailto:info@spurrinai.com" class="support-link">info@spurrinai.com</a> or call our support line at +1 (800) 555-1234.</p>
</div>
</div>
<div class="email-footer">
<p>© 2025 Spurrinai - Healthcare Data Management Platform</p>
<p>This is an automated message. Please do not reply to this email.</p>
<p>Need help? Contact <a href="mailto:support@spurrinai.com" class="support-link">support@spurrinai.com</a></p>
</div>
</div>
</body>
</html>`,
};
try {
const info = await transporter.sendMail(mailOptions);
console.log("info: ", info);
return info;
} catch (error) {
console.error(`Error sending email to ${email}:`, error);
return error;
}
}
// chat-sessions
exports.getChatSessionsByAppUserID = async (req, res) => {
try {
console.log("user data", req.user)
const { role } = req.user;
// Ensure the user has the proper role
// if (!['Superadmin', 'Admin', 9, 8].includes(role)) {
// return res.status(403).json({ error: 'Unauthorized to view chats' });
// }
if (!req.user.id) {
return res.status(400).json({ error: "user id not found" });
}
// Query to fetch app users
const query = `
SELECT session_id,
MIN(session_title) AS session_title,
MIN(created_at) AS created_at
FROM interaction_logs
WHERE app_user_id = ${req.user.id}
AND session_id IS NOT NULL
GROUP BY session_id
ORDER BY session_id DESC;
`;
const session_ids = await db.query(query);
if (session_ids.length === 0) {
return res.status(404).json({ message: 'No interaction logs found for this app user', data: session_ids });
}
res.status(200).json({
message: 'Interaction logs fetched successfully',
data: session_ids,
});
} catch (error) {
console.error('Error fetching interaction logs:', error.message);
res.status(500).json({ error: 'Internal server error' });
}
}
exports.getChatForEachSession = async (req, res) => {
try {
console.log("user data", req.user)
const session_id = req.params.session_id;
console.log("session_id ", session_id)
// Ensure the user has the proper role
// if (!['Superadmin', 'Admin', 9, 8].includes(role)) {
// return res.status(403).json({ error: 'Unauthorized to view chats' });
// }
if (!req.user.id) {
return res.status(400).json({ error: "user id not found" });
}
// Query to fetch app users
const query = `
SELECT * FROM interaction_logs
WHERE app_user_id = ?
AND session_id = ?
AND status = 'Active';
`;
const values = [req.user.id, session_id];
const interaction_logs = await db.query(query, values);
if (interaction_logs.length === 0) {
return res.status(404).json({ message: 'No interaction logs found for this app user or session', data: interaction_logs });
}
res.status(200).json({
message: 'Interaction logs fetched successfully',
data: interaction_logs,
});
} catch (error) {
console.error('Error fetching interaction logs:', error.message);
res.status(500).json({ error: 'Internal server error' });
}
}
exports.deleteChatSessions = async (req, res) => {
const id = req.user.id;
const { session_id } = req.body
console.log("session_id ", session_id)
console.log("app_user_id ", id)
try {
const result = await db.query(
"UPDATE interaction_logs SET session_id = NULL WHERE app_user_id = ? AND session_id = ?",
[id, session_id]
);
if (result.affectedRows === 0) {
return res.status(404).json({ error: "No session found" });
}
res.json({ message: "Chat session deleted successfully" });
} catch (error) {
console.error("Error deleting query title:", error);
res.status(500).json({ error: "Internal server error" });
}
}
exports.clearChatbasedOnSessions = async (req, res) => {
const id = req.user.id;
const { session_id } = req.body
try {
const result = await db.query(
"UPDATE interaction_logs SET status = ? WHERE app_user_id = ? AND session_id = ?",
['Inactive', id, session_id]
);
if (result.affectedRows === 0) {
return res.status(404).json({ error: "No chat found" });
}
res.json({ message: "Chat deleted successfully" });
} catch (error) {
console.error("Error deleting chat:", error);
res.status(500).json({ error: "Internal server error" });
}
}
exports.getChatByTime = async (req, res) => {
try {
console.log("user data", req.user)
const { lastcreated_at } = req.body;
// Ensure the user has the proper role
// if (!['Superadmin', 'Admin', 9, 8].includes(role)) {
// return res.status(403).json({ error: 'Unauthorized to view chats' });
// }
if (!req.user.id) {
return res.status(400).json({ error: "user id not found" });
}
// Query to fetch app users
let results
console.log("last created at", lastcreated_at)
if (!lastcreated_at) { // Handles null, undefined, empty string, etc.
const query = `
SELECT * FROM interaction_logs
WHERE app_user_id = ?;
`;
results = await db.query(query, [req.user.id]);
} else {
console.log("Executing with last_created_at:", lastcreated_at);
const query = `
SELECT * FROM interaction_logs
WHERE app_user_id = ?
AND created_at > ?;
`;
results = await db.query(query, [req.user.id, lastcreated_at]);
}
if (results.length === 0) {
return res.status(404).json({ message: 'No interaction logs found for this app user' });
}
res.status(200).json({
message: 'Interaction logs fetched successfully',
data: results,
});
} catch (error) {
console.error('Error fetching interaction logs:', error.message);
res.status(500).json({ error: 'Internal server error' });
}
}
exports.checkEmailCode = async (req, res) => {
try {
const { email, hospital_code } = req.body;
// Check if the email and code are provided
if (!email || !hospital_code) {
return res.status(400).json({ error: "Email and code are required" });
}
console.log("received data", email, hospital_code)
// Check if the email exists in the database
const useremail = await db.query("SELECT * FROM app_users WHERE email = ?", [email]);
console.log("user email", useremail)
if (useremail.length) {
return res.status(404).json({ error: "Email already in use" });
}
// Check if the code is correct
const usercode = await db.query("SELECT hospital_code FROM hospital_users WHERE hospital_code = ?", [hospital_code]);
console.log("user code", usercode)
if (!usercode.length) {
return res.status(404).json({ error: "Please enter valid hospital code" });
}
// Code is correct, return success response
res.status(200).json({ message: "Email code is correct" });
} catch (error) {
console.error("Error checking email code:", error);
res.status(500).json({ error: "Internal server error" });
}
}
// get popular topics
exports.getPopularTopics = async (req, res) => {
let popularTopics = [];
try {
// Fetch top 4 most viewed questions
console.log("req.user data : ", req.user)
const rows = await getMappedPopularQuestionsAnswers(req.user.hospital_code);
if (!rows) {
popularTopics = []
}
else {
popularTopics = rows;
}
console.log('hospital data : ', rows)
res.status(200).json({
success: true,
data: popularTopics
});
} catch (error) {
console.error('Error fetching popular topics:', error);
res.status(500).json({
success: false,
message: 'Internal server error'
});
}
}
const getMappedPopularQuestionsAnswers = async (hospitalCode) => {
console.log("Hospital code is---", hospitalCode);
try {
const query = `
SELECT il.query, il.response
FROM interaction_logs il
WHERE il.hospital_code = ?
ORDER BY il.created_at DESC -- Sorting by most recent interactions
LIMIT 10; -- Fetch more than 4 to filter unwanted entries
`;
const rows = await db.query(query, [hospitalCode]);
console.log("Fetched questions before filtering:", rows);
// Skip the row if either condition is true
const filteredRows = rows.filter(row =>
!(row.query.toLowerCase().includes("yes") || row.response.includes("Please reply with 'yes'"))
);
// Return only the top 4 filtered results
return filteredRows.slice(0, 4);
} catch (error) {
console.error("Error fetching popular topics:", error.message);
throw new Error("Internal server error");
}
};
exports.changePin = async (req, res) => {
try {
const { current_pin, new_pin } = req.body;
const userId = req.user.id;
if (!current_pin || !new_pin) {
return res.status(400).json({ error: "Current pin and new pin are required" });
}
// Add PIN length validation
if (new_pin.length !== 4 || !/^\d+$/.test(new_pin)) {
return res.status(400).json({ error: "New PIN must be exactly 4 digits" });
}
// Get user's current pin
const userQuery = "SELECT pin_number FROM app_users WHERE id = ?";
const user = await db.query(userQuery, [userId]);
if (!user.length) {
return res.status(404).json({ error: "User not found" });
}
// Verify current pin
if (user[0].pin_number !== current_pin) {
return res.status(400).json({ error: "Current pin is incorrect" });
}
// Check if new pin is same as current pin
if (current_pin === new_pin) {
return res.status(400).json({ error: "New PIN cannot be the same as current PIN" });
}
// Update to new pin
await db.query(
"UPDATE app_users SET pin_number = ? WHERE id = ?",
[new_pin, userId]
);
res.json({ message: "Pin changed successfully" });
} catch (error) {
console.error("Error changing pin:", error);
res.status(500).json({ error: "Internal server error" });
}
};
exports.forgotPin = async (req, res) => {
try {
const { email } = req.body;
if (!email) {
return res.status(400).json({ error: "Email is required" });
}
// Get user details
const userQuery = `
SELECT au.id, au.username, au.pin_number, au.hospital_code, h.name_hospital
FROM app_users au
JOIN hospitals h ON au.hospital_code = h.hospital_code
WHERE au.email = ?
`;
const user = await db.query(userQuery, [email]);
if (!user.length) {
return res.status(404).json({ error: "User not found" });
}
const userData = user[0];
// Send pin via email
const mailOptions = {
from: "kavya.j@tech4biz.io",
to: email,
subject: "Your Spurrinai PIN",
html: `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Your PIN - Spurrinai Medical Platform</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Syne:wght@400..800&display=swap');
body {
font-family: 'Inter', sans-serif;
margin: 0;
padding: 0;
background-color: #ebf3fa;
color: #333;
}
.email-container {
max-width: 600px;
margin: 20px auto;
background: white;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
}
.email-header {
background: linear-gradient(135deg, #2193b0, #6dd5ed);
padding: 30px;
text-align: center;
color: white;
}
.hospital-name {
display: inline-block;
background-color: rgba(255, 255, 255, 0.2);
padding: 5px 15px;
border-radius: 20px;
font-size: 14px;
margin-bottom: 10px;
}
.email-content {
padding: 40px 30px;
}
.greeting {
font-size: 30px;
font-weight: 700;
margin-bottom: 20px;
color: #303030;
}
.pin-display {
background-color: #f5f9fc;
border: 1px solid #e0e9f0;
border-radius: 8px;
padding: 20px;
margin: 25px 0;
text-align: center;
}
.pin {
font-family: 'Courier New', monospace;
font-size: 32px;
letter-spacing: 6px;
color: #2193b0;
font-weight: bold;
padding: 10px 0;
}
.security-note {
margin-top: 30px;
padding-top: 20px;
border-top: 1px solid #eee;
font-size: 14px;
color: #666;
}
.email-footer {
background-color: #f5f9fc;
padding: 20px;
text-align: center;
font-size: 13px;
color: #888;
border-top: 1px solid #e0e9f0;
}
</style>
</head>
<body>
<div class="email-container">
<div class="email-header">
<div class="hospital-name">${userData.name_hospital}</div>
<h1>Your PIN Information</h1>
</div>
<div class="email-content">
<div class="greeting">Hello ${userData.username},</div>
<p>Here is your PIN for the Spurrinai healthcare platform:</p>
<div class="pin-display">
<div class="pin">${userData.pin_number}</div>
</div>
<div class="security-note">
<p>For security reasons, please do not share this PIN with anyone. If you did not request this information, please contact our support team immediately.</p>
</div>
</div>
<div class="email-footer">
<p>© 2025 Spurrinai - Healthcare Data Management Platform</p>
<p>This is an automated message. Please do not reply to this email.</p>
<p>Need help? Contact <a href="mailto:support@spurrinai.com">support@spurrinai.com</a></p>
</div>
</div>
</body>
</html>`
};
await transporter.sendMail(mailOptions);
res.json({ message: "PIN has been sent to your email" });
} catch (error) {
console.error("Error in forgot pin:", error);
res.status(500).json({ error: "Internal server error" });
}
};
// const bcrypt = require("bcrypt");
// const db = require("../config/database"); // Database connection
// const fs = require("fs");
// const JWT_ACCESS_TOKEN_SECRET = process.env.JWT_ACCESS_TOKEN_SECRET;
// const JWT_ACCESS_TOKEN_EXPIRY = "5h";
// const jwt = require("jsonwebtoken");
// const nlp = require("compromise");
// const nodemailer = require("nodemailer");
// const sender_mail = process.env.mail;
// const sender_app_password = process.env.apppassword;
// const sender_port = process.env.SENDER_PORT;
// const sender_security = process.env.SENDER_SECURITY;
// const path = require('path')
// const { emitEvent } = require("../services/secondaryWebsocket");
// console.log('sender port : ', sender_port);
// console.log('sender security : ', sender_security);
// // zoho transporter
// const transporter = nodemailer.createTransport({
// host: "smtp.zoho.com",
// port: 465,
// secure: true,
// auth: {
// user: "info@spurrin.com",
// pass: "wTcEi6ME4yfc"
// },
// tls: {
// rejectUnauthorized: false, // Allow self-signed certificates
// minVersion: "TLSv1.2"
// }
// });
// exports.initWebSocket = (io) => {
// io.on("connection", (socket) => {
// console.log("Hospital connected:", socket.id);
// socket.on("register_hospital", (hospitalCode) => {
// hospitalSockets[hospitalCode] = socket;
// console.log(`Hospital ${hospitalCode} registered.`);
// });
// socket.on("disconnect", () => {
// const hospitalCode = Object.keys(hospitalSockets).find(
// (key) => hospitalSockets[key] === socket
// );
// if (hospitalCode) delete hospitalSockets[hospitalCode];
// console.log(`Hospital ${hospitalCode} disconnected.`);
// });
// });
// };
// exports.uploadIdPhoto = async (req, res) => {
// try {
// // Extracting user ID and hospital code
// const userId = parseInt(req.params.id, 10); // User ID from route
// const { hospital_code } = req.user; // Authenticated user's hospital code
// // Check if user ID is valid
// if (isNaN(userId)) {
// console.error("Invalid User ID:", userId);
// return res.status(400).json({ error: "Invalid user ID" });
// }
// // Check if a file was uploaded
// if (!req.file) {
// console.error("No file uploaded");
// return res.status(400).json({ error: "No file uploaded" });
// }
// const photoPath = `/uploads/id_photos/${req.file.filename}`;
// // Verify app user is part of the same hospital
// const query = `
// SELECT hospital_code FROM app_users WHERE id = ? AND hospital_code = ?
// `;
// const result = await db.query(query, [userId, hospital_code]);
// if (result.length === 0) {
// console.error(
// "Authorization failed for user ID:",
// userId,
// "with hospital_code:",
// hospital_code
// );
// return res
// .status(403)
// .json({ error: "You are not authorized to upload ID for this user" });
// }
// // Update the ID photo path in the database
// await db.query("UPDATE app_users SET id_photo_url = ? WHERE id = ?", [
// photoPath,
// userId,
// ]);
// res.status(200).json({
// message: "ID photo uploaded successfully!",
// id_photo_url: photoPath,
// });
// } catch (error) {
// console.error("Error uploading ID photo:", error.message);
// res.status(500).json({ error: "Internal server error" });
// }
// };
// exports.updateSettings = async (req, res) => {
// try {
// const userId = req.user.id; // Assuming user is authenticated and userId is available
// const { pin, pin_enabled, remember_me } = req.body;
// console.log("data---",pin,pin_enabled,remember_me)
// // if (typeof pin_enabled !== 'boolean' || typeof remember_me !== 'boolean') {
// // return res.status(400).json({ error: 'Invalid data format' });
// // }
// // Validate pin (if provided)
// if (pin && (typeof pin !== 'string' || pin.length !== 4)) {
// return res.status(400).json({ error: 'Invalid PIN format. Must be a 4-digit string.' });
// }
// // Determine expiry based on remember_me
// let expiresIn = '5h';
// let expiryTimestamp = new Date();
// if (remember_me) {
// expiresIn = '30d';
// expiryTimestamp.setDate(expiryTimestamp.getDate() + 30);
// } else {
// expiryTimestamp.setHours(expiryTimestamp.getHours() + 5);
// }
// // Generate new access token
// const payload = { id: userId, role: 'AppUser' };
// const accessToken = jwt.sign(payload, process.env.JWT_ACCESS_TOKEN_SECRET, {
// expiresIn: expiresIn,
// });
// // Update user settings and access token
// const query = `UPDATE app_users SET pin_number = ?, pin_enabled = ?, remember_me = ?, access_token = ?, access_token_expiry = ? WHERE id = ?`;
// const result=await db.query(query, [pin, pin_enabled, remember_me, accessToken, expiryTimestamp, userId]);
// if (result.affectedRows > 0) {
// console.log("Table updated successfully.");
// } else {
// console.log("Table not updated. No matching user found.");
// }
// res.status(200).json({ message: 'Settings updated successfully.', accessToken });
// } catch (error) {
// console.error('Error updating settings:', error);
// res.status(500).json({ error: 'Internal Server Error' });
// }
// };
// exports.hitlike = async (req, res) => {
// try {
// // Extract user ID and session ID from the request
// const { session_id, id } = req.body;
// const log_id = id;
// const app_user_id = req.user.id;
// // Check if both app_user_id and session_id are provided
// if (!app_user_id || !session_id || !log_id) {
// return res.status(400).json({
// status: 'error',
// message: 'app user id and session id and log id are required',
// });
// }
// // Query to toggle the is_liked value
// const toggleQuery = `
// UPDATE interaction_logs
// SET is_liked = NOT is_liked
// WHERE app_user_id = ? AND session_id = ? AND id = ?
// `;
// // Execute the query
// const result = await db.query(toggleQuery, [app_user_id, session_id,log_id]);
// // Check if any rows were affected
// if (result.affectedRows > 0) {
// return res.status(200).json({
// status: 'success',
// message: 'Like updated successfully',
// data: {
// app_user_id,
// session_id,
// is_liked: result.changedRows > 0 ? 1 : 0, // 1 if changed, 0 if not
// },
// });
// } else {
// return res.status(404).json({
// status: 'error',
// message: 'No matching record found to toggle',
// });
// }
// } catch (error) {
// console.error('Error during like toggle:', error);
// return res.status(500).json({
// status: 'error',
// message: 'Internal server error',
// });
// }
// };
// exports.signup = async (req, res) => {
// try {
// const { pin, pin_status,remember_me, email, password, hospital_code, username } = req.body;
// console.log("pin--",pin)
// console.log("pin_status",pin_status)
// console.log("email--",email)
// console.log('password---',password)
// console.log("hospital_code---",hospital_code)
// console.log("username--",username)
// console.log("remember_me--",remember_me)
// if (!email || !password || !hospital_code || !username) {
// return res.status(400).json({
// error: "Email, password, username, and hospital code are required",
// });
// }
// const pin_enabled = (pin_status === undefined || pin_status === '') ? 0 : pin_status;
// const remember_me_ = (remember_me === undefined || remember_me === '') ? 0 : remember_me;
// // Check if the hospital_code exists in the `hospitals` table
// const hospitalQuery =
// "SELECT hospital_code FROM hospitals WHERE hospital_code = ?";
// const hospitalResult = await db.query(hospitalQuery, [hospital_code]);
// if (hospitalResult.length === 0) {
// return res.status(404).json({ error: "Invalid hospital code" });
// }
// // Check if the email is already in use
// const userQuery = "SELECT id FROM app_users WHERE email = ?";
// const userResult = await db.query(userQuery, [email]);
// if (userResult.length > 0) {
// return res.status(400).json({ error: "Email already in use" });
// }
// // Hash the password
// const hashPassword = await bcrypt.hash(password, 10);
// // Insert the new app user into the `app_users` table
// const insertQuery = `
// INSERT INTO app_users (email, hash_password, hospital_code, status, username, pin_number, pin_enabled, remember_me )
// VALUES (?, ?, ?, 'Pending', ?, ?, ?,?)
// `;
// const result = await db.query(insertQuery, [
// email,
// hashPassword,
// hospital_code,
// username,
// pin, // Set pin to null if not provided
// pin_enabled,
// remember_me_
// ]);
// const userId = result.insertId; // Get the new user's ID
// // Check if a file was uploaded
// if (!req.file) {
// return res.status(400).json({ error: "ID photo is required" });
// }
// const filePath = `/uploads/id_photos/${req.file.filename}`; // Correct file path
// // Update the ID photo path in the database
// await db.query(
// "UPDATE app_users SET id_photo_url = ?, upload_status = ? WHERE id = ?",
// [filePath, "1", userId]
// );
// // ✅ Notify hospitals in the SECONDARY WebSocket instance
// emitEvent("new_user", {
// message: `A new user has been created for hospital ${hospital_code}.`,
// user: { id: userId, username, email },
// });
// res.status(201).json({
// message: "User signed up and ID photo uploaded successfully!",
// data: {
// id: userId,
// email,
// hospital_code,
// username,
// id_photo_url: filePath,
// pin: pin || null,
// pin_status : pin_status,
// remember_me: remember_me
// },
// });
// } catch (error) {
// console.error("Error during signup and ID photo upload:", error.message);
// res.status(500).json({ error: "Internal server error" });
// }
// };
// exports.login = async (req, res) => {
// try {
// const { email, password } = req.body;
// let remember_me;
// if (!email || !password) {
// return res.status(400).json({ error: "Email and password are required" });
// }
// console.log("email----",email)
// // Check if the user exists
// const query = "SELECT * FROM app_users WHERE email = ?";
// const result = await db.query(query, [email]);
// console.log("result---",result)
// if (result.length === 0) {
// return res.status(404).json({ error: "User not found" });
// }
// const user = result[0];
// remember_me = user.remember_me
// const hospitalData = await db.query("SELECT * FROM hospitals WHERE hospital_code = ?", [user.hospital_code]);
// // if (hospitalData.publicSignupEnabled) {
// // throw new Error("Hospital not found");
// // }
// if (user.status === "Pending" && !hospitalData[0].publicSignupEnabled) {
// return res.status(404).json({ message: "Your Account is Under Review" });
// }
// if (user.status === "Inactive" && !hospitalData[0].publicSignupEnabled) {
// return res.status(404).json({ message: "Contact admin your account is not approved" });
// }
// if(hospitalData[0].publicSignupEnabled){
// user.status = "Active"
// }
// // Validate the password
// const validPassword = await bcrypt.compare(password, user.hash_password);
// if (!validPassword) {
// return res.status(401).json({ error: "Invalid email or password" });
// }
// // Determine expiry based on remember_me
// let expiresIn = "5h";
// let expiryTimestamp = new Date();
// let rememberMeValue = remember_me;
// if (rememberMeValue === undefined) rememberMeValue = user.remember_me;
// if (rememberMeValue === true || rememberMeValue === 1 || rememberMeValue === "1" || rememberMeValue === "true") {
// const updateQuery = `
// UPDATE app_users
// SET remember_me = ?
// WHERE id = ?
// `;
// await db.query(updateQuery, [remember_me,user.id]);
// expiresIn = "30d";
// expiryTimestamp.setDate(expiryTimestamp.getDate() + 30);
// } else {
// expiryTimestamp.setHours(expiryTimestamp.getHours() + 5);
// }
// // Generate a new access token
// const payload = { id: user.id, email: user.email, role: "AppUser" };
// const accessToken = jwt.sign(payload, process.env.JWT_ACCESS_TOKEN_SECRET, {
// expiresIn: expiresIn,
// });
// // SQL query to fetch hospital data based on the provided hospital_code
// const query_hospital = `
// SELECT * FROM hospitals WHERE hospital_code = ?;
// `;
// // Run the query
// const result_hospital = await db.query(query_hospital, [user.hospital_code]);
// // hospital users
// const queryHospitalUsr = `
// SELECT * FROM hospital_users WHERE hospital_code = ?;
// `;
// // Run the query
// const resultHospitalUsr = await db.query(queryHospitalUsr, [user.hospital_code]);
// const hospitalUser = resultHospitalUsr[0];
// if (!hospitalUser) {
// return res.status(404).json({ error: "Hospital user not found" });
// }
// // Update the access token and expiry in the database
// const updateQuery = `
// UPDATE app_users
// SET access_token = ?, access_token_expiry = ?, remember_me = ?
// WHERE id = ?
// `;
// await db.query(updateQuery, [accessToken, expiryTimestamp, (rememberMeValue === true || rememberMeValue === 1 || rememberMeValue === "1" || rememberMeValue === "true") ? 1 : 0, user.id]);
// // Send response
// res.status(200).json({
// message: "Login successful",
// user: {
// id: user.id,
// email: user.email,
// pin: user.pin_number,
// pin_enabled: user.pin_enabled,
// hospital_code: user.hospital_code,
// status: user.status,
// hospital_name: result_hospital[0].name_hospital,
// primary_color: result_hospital[0].primary_color,
// secondary_color: result_hospital[0].secondary_color,
// upload_status: user.upload_status,
// id_photo_url: user.id_photo_url,
// primary_admin_email: result_hospital[0].primary_admin_email,
// mobile_number: result_hospital[0].mobile_number,
// username: user.username,
// logo_url: resultHospitalUsr[0].profile_photo_url,
// query_title: user.query_title,
// remember_me: (rememberMeValue === true || rememberMeValue === 1 || rememberMeValue === "1" || rememberMeValue === "true") ? 1 : 0
// },
// accessToken,
// });
// } catch (error) {
// console.error("Error during login:", error.message);
// res.status(500).json({ error: "Internal server error" });
// }
// };
// exports.checkPin = async (req, res) => {
// try {
// const { email, pin } = req.body;
// if (!email || !pin) {
// return res.status(400).json({ error: "Email and Pin are required" });
// }
// // Check if the user exists
// const query = "SELECT * FROM app_users WHERE email = ?";
// const result = await db.query(query, [email]);
// if (result.length === 0) {
// return res.status(404).json({ error: "User not found" });
// }
// const user = result[0];
// const hospitalData = await db.query("SELECT * FROM hospitals WHERE hospital_code = ?", [user.hospital_code]);
// if (user.status === "Pending" && !hospitalData[0].publicSignupEnabled) {
// throw new Error("Your Account is Under Review");
// }
// if (user.status === "Inactive" && !hospitalData[0].publicSignupEnabled) {
// throw new Error("Contact admin your account is not approved");
// }
// // Check PIN if PIN status is enabled
// if (pin !== user.pin_number) {
// return res.status(401).json({
// error: "Invalid PIN",
// requires_pin: true,
// message: "Incorrect PIN. Please try again"
// });
// }
// // Send response
// res.status(200).json({
// message: "Pin verified successfully",
// });
// } catch (error) {
// console.error("Error during login:", error.message);
// res.status(500).json({ error: "Internal server error" });
// }
// };
// exports.logout = async (req, res) => {
// try {
// const userId = req.user.id; // Assuming the user is authenticated via middleware
// // Check if the user exists
// const query = "SELECT * FROM app_users WHERE id = ?";
// const result = await db.query(query, [userId]);
// if (result.length === 0) {
// return res.status(404).json({ error: "User not found" });
// }
// // Invalidate the access token in the database
// const updateQuery = `
// UPDATE app_users
// SET access_token = NULL, access_token_expiry = NULL
// WHERE id = ?
// `;
// await db.query(updateQuery, [userId]);
// res.status(200).json({ message: "Logout successful" });
// } catch (error) {
// console.error("Error during logout:", error.message);
// res.status(500).json({ error: "Internal server error" });
// }
// };
// // controller.js
// exports.getAppUsersByHospitalCode = async (req, res) => {
// try {
// // Extract the hospital_code from the token (req.user object)
// const userId = req.user.id;
// if (!userId) {
// return res.status(400).json({ error: "User not found for the token" });
// }
// // Query to fetch hospital users based on the hospital_code
// const query = `
// SELECT id, email, status,hospital_code
// FROM app_users
// WHERE id = ?;
// `;
// const result = await db.query(query, [userId]);
// if (result.length === 0) {
// return res
// .status(404)
// .json({ error: "No users found for the specified Token" });
// }
// const hospitalData = await db.query("SELECT * FROM hospitals WHERE hospital_code = ?", [result[0].hospital_code]);
// if(hospitalData[0].publicSignupEnabled){
// result[0].status = 'Active'
// }
// // Send the response with the users data
// res.status(200).json({
// message: "Hospital users fetched successfully",
// user: result[0],
// });
// } catch (error) {
// console.error("Error fetching hospital users:", error.message);
// res.status(500).json({ error: "Internal server error" });
// }
// };
// exports.approveUserId = async (req, res) => {
// try {
// const appUserId = req.params.id; // App user ID to approve
// const { role } = req.user; // Authenticated user's details
// const { Action } = req.body;
// const { hospital_code } = req.user;
// if (!req.body.Action) {
// return res.status(400).json({ error: "Action is required" });
// }
// if (!["Superadmin", "Admin", 8].includes(role)) {
// return res.status(403).json({ error: "Unauthorized to approve IDs" });
// }
// const query = `
// SELECT hospital_code FROM app_users WHERE id = ? AND hospital_code = ?
// `;
// const result = await db.query(query, [appUserId, hospital_code]);
// if (result.length === 0) {
// return res
// .status(403)
// .json({ error: "User does not belong to your hospital" });
// }
// // Approve the ID
// if (Action == "Reject") {
// await db.query('UPDATE app_users SET status = "Inactive" WHERE id = ?', [
// appUserId,
// ]);
// res.status(200).json({ message: "ID Rejected successfully" });
// } else if (Action == "Approve") {
// await db.query('UPDATE app_users SET status = "Active" WHERE id = ?', [
// appUserId,
// ]);
// res.status(200).json({ message: "ID approved successfully" });
// }
// } catch (error) {
// console.error("Error approving ID:", error.message);
// res.status(500).json({ error: "Internal server error" });
// }
// };
// exports.getAppUsers = async (req, res) => {
// try {
// const { role } = req.user;
// // Ensure the user has the proper role
// if (!["Superadmin", "Admin", 9, 8].includes(role)) {
// return res.status(403).json({ error: "Unauthorized to view app users" });
// }
// // Query to fetch app users
// const query = `
// SELECT * FROM app_users;
// `;
// const users = await db.query(query);
// if (users.length === 0) {
// return res
// .status(404)
// .json({ message: "No app users found for this hospital" });
// }
// res.status(200).json({
// message: "App users fetched successfully",
// data: users,
// });
// } catch (error) {
// console.error("Error fetching app users:", error.message);
// res.status(500).json({ error: "Internal server error" });
// }
// };
// exports.getAppUserByHospitalId = async (req, res) => {
// try {
// const { role } = req.user;
// const { id } = req.params; // Extract user ID from request parameters
// // Log authenticated user details
// // Ensure the user has the proper role
// if (!["Superadmin", "Admin", 8, 9].includes(role)) {
// return res.status(403).json({ error: "Unauthorized to view app users" });
// }
// // fetching hospital code from hospital id
// const query1 = `SELECT * FROM hospitals WHERE id = ?`;
// const [result1] = await db.query(query1, [id]);
// const hospital_code = result1.hospital_code;
// // Query to fetch the app user by hospital_code
// const query = `SELECT * FROM app_users WHERE hospital_code = ?`;
// const users = await db.query(query, [hospital_code]);
// if (users.length === 0) {
// return res.status(404).json({ message: "App users not found" });
// }
// res.status(200).json({
// message: "App user fetched successfully",
// data: users, // Return single user object
// });
// } catch (error) {
// console.error("Error fetching app user:", error.message);
// res.status(500).json({ error: "Internal server error" });
// }
// };
// exports.deleteAppUser = async (req, res) => {
// try {
// const { id } = req.params;
// const { hospital_code } = req.user;
// // Check if the user exists
// // const [users] = await db.query('SELECT * FROM app_users WHERE id = ?', [id]); // ✅ Properly handle array
// // if (!users || users.length === 0) {
// // return res.status(404).json({ error: 'User not found' });
// // }
// const appUserquery = "SELECT * FROM app_users WHERE id = ?";
// const users = await db.query(appUserquery, [id]);
// if (users.length === 0) {
// return res
// .status(404)
// .json({ message: "No app users found for this hospital" });
// }
// // Ensure only Admin or Superadmin can delete users
// if (!["Admin", "Superadmin", 8, 7].includes(req.user.role)) {
// return res.status(403).json({ error: "Unauthorized to delete users" });
// }
// // Ensure user belongs to the same hospital
// const query =
// "SELECT hospital_code,id_photo_url FROM app_users WHERE id = ? AND hospital_code = ?";
// const result = await db.query(query, [id, hospital_code]);
// if (!result || result.length === 0) {
// return res
// .status(403)
// .json({ error: "User does not belong to your hospital" });
// }
// // Unlink (delete) the associated file if it exists
// const filePath = path.join(__dirname, '..','..', 'uploads', result[0].id_photo_url.replace(/^\/uploads\//, ''));
// fs.access(filePath, fs.constants.F_OK, (err) => {
// if (err) {
// console.error(`File not found: ${filePath}`);
// return;
// }
// fs.unlink(filePath, (err) => {
// if (err) {
// console.error('Error deleting file:', err.message);
// } else {
// console.log('File deleted successfully:', filePath);
// }
// });
// });
// // Delete the user
// const deleteResult = await db.query("DELETE FROM app_users WHERE id = ?", [
// id,
// ]);
// if (deleteResult.affectedRows === 0) {
// return res.status(404).json({ error: "User not found" });
// }
// res.status(200).json({ message: "User deleted successfully" });
// } catch (error) {
// console.error("Error deleting user:", error.message);
// res.status(500).json({ error: "Internal server error" });
// }
// };
// // query title CRUD
// exports.updateQueryTitle = async (req, res) => {
// const id = req.user.id;
// const { query_title } = req.body;
// if (!query_title) {
// return res.status(400).json({ error: "query_title is required" });
// }
// try {
// const result = await db.query(
// "UPDATE app_users SET query_title = ? WHERE id = ?",
// [query_title, id]
// );
// if (result.affectedRows === 0) {
// return res.status(404).json({ error: "User not found" });
// }
// res.json({ message: "Query title updated successfully" });
// } catch (error) {
// console.error("Error updating query title:", error);
// res.status(500).json({ error: "Internal server error" });
// }
// };
// // Delete query_title for a user by user ID
// exports.getShortTitle = (req, res) => {
// const { question } = req.body;
// console.log("Question: ", question);
// if (!question) return res.status(400).json({ error: "No question provided" });
// let shortTitle = nlp(question).sentences().toTitleCase().out("text");
// // Remove unnecessary question words
// shortTitle = shortTitle
// .replace(
// /^(What|How|Why|When|Where|Which|Who|Is|Are|Do|Does|Can|Could)\s+/i,
// ""
// )
// .trim();
// if (!shortTitle)
// return res.status(400).json({ error: "Invalid question format" });
// console.log("short question:", shortTitle);
// res.json({ query_title: shortTitle });
// };
// exports.deleteQueryTitle = async (req, res) => {
// const id = req.user.id;
// try {
// const result = await db.query(
// "UPDATE app_users SET query_title = NULL WHERE id = ?",
// [id]
// );
// if (result.affectedRows === 0) {
// return res.status(404).json({ error: "User not found" });
// }
// res.json({ message: "Query title deleted successfully" });
// } catch (error) {
// console.error("Error deleting query title:", error);
// res.status(500).json({ error: "Internal server error" });
// }
// };
// exports.sendOtp = async (req, res) => {
// try {
// const { email } = req.body;
// // Validate email input
// if (!email) {
// return res.status(400).json({ error: "Email is required" });
// }
// // Check if user exists
// const user = await db.query(
// "SELECT id, username, hospital_code FROM app_users WHERE email = ?",
// [email]
// );
// if (!user.length) {
// return res.status(404).json({ error: "User not found" });
// }
// console.log("user", user);
// const userId = user[0].id;
// const hospital_code = user[0].hospital_code;
// // fetch hospital name of app_user
// const hospital = await db.query(
// "SELECT name_hospital FROM hospitals WHERE hospital_code = ?",
// [hospital_code]
// );
// console.log("hospital result : ", hospital[0].name_hospital);
// // Generate a 6-digit OTP
// const otp = Math.floor(100000 + Math.random() * 900000).toString();
// const expiresAt = new Date(Date.now() + 2 * 60 * 60 * 1000); // OTP expires in 1 hour
// console.log("otp : ", otp, "expiresAt: ", expiresAt);
// // Store OTP in database
// await db.query(
// "UPDATE app_users SET otp_code = ?, otp_expires_at = ? WHERE id = ?",
// [otp, expiresAt, userId]
// );
// // // Send OTP via email
// const info = await sendMail(
// email,
// hospital[0].name_hospital,
// user[0].username,
// otp
// );
// res.json({ message: "OTP sent successfully", email_status: info.response });
// } catch (error) {
// console.error("Error sending OTP:", error);
// res.status(500).json({ error: "Internal server error" });
// }
// };
// exports.changePassword = async (req, res) => {
// try {
// const { email, otp, new_password } = req.body;
// console.log("email : ", email);
// // Validate inputs
// if (!email || !otp || !new_password) {
// return res
// .status(400)
// .json({ error: "Email, OTP, and new password are required" });
// }
// // Fetch OTP from the database
// const user = await db.query(
// "SELECT id, otp_code, otp_expires_at FROM app_users WHERE email = ?",
// [email]
// );
// if (!user.length) {
// return res.status(404).json({ error: "User not found" });
// }
// const userData = user[0];
// // ✅ Check if OTP matches
// if (userData.otp_code !== otp) {
// return res.status(400).json({ error: "Invalid OTP" });
// }
// // ✅ Check if OTP is expired
// if (new Date() > new Date(userData.otp_expires_at)) {
// return res.status(400).json({ error: "OTP expired. Request a new one." });
// }
// // ✅ Hash the new password
// const hashedPassword = await bcrypt.hash(new_password, 10);
// // ✅ Update password in DB & clear OTP
// await db.query(
// "UPDATE app_users SET hash_password = ?, otp_code = NULL, otp_expires_at = NULL WHERE id = ?",
// [hashedPassword, userData.id]
// );
// res.json({ message: "Password changed successfully!" });
// } catch (error) {
// console.error("Error resetting password:", error);
// res.status(500).json({ error: "Internal server error" });
// }
// };
// async function sendMail(email, hospital_name, username, otp) {
// const mailOptions = {
// from: sender_mail, // Sender's email
// to: email, // Recipient's email
// subject: "Spurrinai Login Credentials", // Email subject
// html: `<!DOCTYPE html>
// <html lang="en">
// <head>
// <meta charset="UTF-8">
// <meta name="viewport" content="width=device-width, initial-scale=1.0">
// <title>Reset Your Password - Spurrinai Medical Platform</title>
// <style>
// @import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Syne:wght@400..800&display=swap');
// body {
// font-family: 'Inter', sans-serif;
// margin: 0;
// padding: 0;
// background-color: #ebf3fa;
// color: #333;
// }
// .email-container {
// max-width: 600px;
// margin: 20px auto;
// background: white;
// border-radius: 10px;
// overflow: hidden;
// box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
// }
// .email-header {
// background: linear-gradient(135deg, #2193b0, #6dd5ed);
// padding: 30px;
// text-align: center;
// color: white;
// }
// .hospital-name {
// display: inline-block;
// background-color: rgba(255, 255, 255, 0.2);
// padding: 5px 15px;
// border-radius: 20px;
// font-size: 14px;
// margin-bottom: 10px;
// }
// .email-header h1 {
// margin: 10px 0 0;
// font-size: 26px;
// font-weight: 500;
// }
// .email-content {
// padding: 40px 30px;
// }
// .greeting {
// font-size: 30px;
// font-weight: 700;
// margin-bottom: 20px;
// color: #303030;
// }
// .greeting-text{
// font-size: 18px;
// font-weight: 400;
// margin-bottom: 20px;
// line-height: 1.7;
// color: #303030;
// }
// .verification-code {
// background-color: #f5f9fc;
// border: 1px solid #e0e9f0;
// border-radius: 8px;
// padding: 20px;
// margin: 25px 0;
// text-align: center;
// }
// .code {
// font-family: 'Courier New', monospace;
// font-size: 32px;
// letter-spacing: 6px;
// color: #2193b0;
// font-weight: bold;
// padding: 10px 0;
// }
// .reset-button {
// display: block;
// background-color: #2193b0;
// color: white;
// text-decoration: none;
// text-align: center;
// padding: 15px 20px;
// border-radius: 5px;
// margin: 30px auto;
// max-width: 250px;
// font-weight: 500;
// transition: background-color 0.3s;
// }
// .reset-button:hover {
// background-color: #1a7b92;
// }
// .expiry-note {
// background-color: #fff8e1;
// border-left: 4px solid #ffc107;
// padding: 12px 15px;
// margin: 25px 0;
// font-size: 14px;
// color: #856404;
// }
// .security-note {
// margin-top: 30px;
// padding-top: 20px;
// border-top: 1px solid #eee;
// font-size: 14px;
// color: #666;
// }
// .email-footer {
// background-color: #f5f9fc;
// padding: 20px;
// text-align: center;
// font-size: 13px;
// color: #888;
// border-top: 1px solid #e0e9f0;
// }
// .support-link {
// color: #2193b0;
// text-decoration: none;
// }
// .device-info {
// margin-top: 20px;
// background-color: #f5f9fc;
// padding: 15px;
// border-radius: 6px;
// font-size: 14px;
// }
// .device-info p {
// margin: 5px 0;
// color: #666;
// }
// </style>
// </head>
// <body>
// <div class="email-container">
// <div class="email-header">
// <div class="hospital-name"> ${hospital_name}</div>
// <h1>Reset Your Password</h1>
// </div>
// <div class="email-content">
// <div class="greeting">Hello ${username},</div>
// <p class="greeting-text" >We received a request to <strong>reset the password</strong> for your account on the <strong> Spurrinai healthcare platform</strong>. For your security reasons, please verify this action.</p>
// <div class="verification-code">
// <p>Please enter this verification code:</p>
// <div class="code">${otp}</div>
// <p>on the password reset screen</p>
// </div>
// <a href="spurrinai://ResetPassword/${otp}" class="reset-button">Reset Password</a>
// <div class="expiry-note">
// <strong>Note:</strong> This verification code will expire in 2 hours for security reasons.
// </div>
// <div class="security-note">
// <p>If you did not request this password reset, please contact our IT security team immediately at <a href="mailto:info@spurrinai.com" class="support-link">info@spurrinai.com</a> or call our support line at +1 (800) 555-1234.</p>
// </div>
// </div>
// <div class="email-footer">
// <p>© 2025 Spurrinai - Healthcare Data Management Platform</p>
// <p>This is an automated message. Please do not reply to this email.</p>
// <p>Need help? Contact <a href="mailto:support@spurrinai.com" class="support-link">support@spurrinai.com</a></p>
// </div>
// </div>
// </body>
// </html>`,
// };
// try {
// const info = await transporter.sendMail(mailOptions);
// console.log("info: ", info);
// return info;
// } catch (error) {
// console.error(`Error sending email to ${email}:`, error);
// return error;
// }
// }
// // chat-sessions
// exports.getChatSessionsByAppUserID = async (req, res) => {
// try {
// console.log("user data", req.user)
// const { role } = req.user;
// // Ensure the user has the proper role
// // if (!['Superadmin', 'Admin', 9, 8].includes(role)) {
// // return res.status(403).json({ error: 'Unauthorized to view chats' });
// // }
// if (!req.user.id) {
// return res.status(400).json({ error: "user id not found" });
// }
// // Query to fetch app users
// const query = `
// SELECT session_id,
// MIN(session_title) AS session_title,
// MIN(created_at) AS created_at
// FROM interaction_logs
// WHERE app_user_id = ${req.user.id}
// AND session_id IS NOT NULL
// GROUP BY session_id
// ORDER BY session_id DESC;
// `;
// const session_ids = await db.query(query);
// if (session_ids.length === 0) {
// return res.status(404).json({ message: 'No interaction logs found for this app user', data: session_ids });
// }
// res.status(200).json({
// message: 'Interaction logs fetched successfully',
// data: session_ids,
// });
// } catch (error) {
// console.error('Error fetching interaction logs:', error.message);
// res.status(500).json({ error: 'Internal server error' });
// }
// }
// exports.getChatForEachSession = async (req, res) => {
// try {
// console.log("user data", req.user)
// const session_id = req.params.session_id;
// console.log("session_id ", session_id)
// // Ensure the user has the proper role
// // if (!['Superadmin', 'Admin', 9, 8].includes(role)) {
// // return res.status(403).json({ error: 'Unauthorized to view chats' });
// // }
// if (!req.user.id) {
// return res.status(400).json({ error: "user id not found" });
// }
// // Query to fetch app users
// const query = `
// SELECT * FROM interaction_logs
// WHERE app_user_id = ?
// AND session_id = ?
// AND status = 'Active';
// `;
// const values = [req.user.id, session_id];
// const interaction_logs = await db.query(query, values);
// if (interaction_logs.length === 0) {
// return res.status(404).json({ message: 'No interaction logs found for this app user or session', data: interaction_logs });
// }
// res.status(200).json({
// message: 'Interaction logs fetched successfully',
// data: interaction_logs,
// });
// } catch (error) {
// console.error('Error fetching interaction logs:', error.message);
// res.status(500).json({ error: 'Internal server error' });
// }
// }
// exports.deleteChatSessions = async (req, res) => {
// const id = req.user.id;
// const { session_id } = req.body
// console.log("session_id ", session_id)
// console.log("app_user_id ", id)
// try {
// const result = await db.query(
// "UPDATE interaction_logs SET session_id = NULL WHERE app_user_id = ? AND session_id = ?",
// [id, session_id]
// );
// if (result.affectedRows === 0) {
// return res.status(404).json({ error: "No session found" });
// }
// res.json({ message: "Chat session deleted successfully" });
// } catch (error) {
// console.error("Error deleting query title:", error);
// res.status(500).json({ error: "Internal server error" });
// }
// }
// exports.clearChatbasedOnSessions = async (req, res) => {
// const id = req.user.id;
// const { session_id } = req.body
// try {
// const result = await db.query(
// "UPDATE interaction_logs SET status = ? WHERE app_user_id = ? AND session_id = ?",
// ['Inactive', id, session_id]
// );
// if (result.affectedRows === 0) {
// return res.status(404).json({ error: "No chat found" });
// }
// res.json({ message: "Chat deleted successfully" });
// } catch (error) {
// console.error("Error deleting chat:", error);
// res.status(500).json({ error: "Internal server error" });
// }
// }
// exports.getChatByTime = async (req, res) => {
// try {
// console.log("user data", req.user)
// const { lastcreated_at } = req.body;
// // Ensure the user has the proper role
// // if (!['Superadmin', 'Admin', 9, 8].includes(role)) {
// // return res.status(403).json({ error: 'Unauthorized to view chats' });
// // }
// if (!req.user.id) {
// return res.status(400).json({ error: "user id not found" });
// }
// // Query to fetch app users
// let results
// console.log("last created at", lastcreated_at)
// if (!lastcreated_at) { // Handles null, undefined, empty string, etc.
// const query = `
// SELECT * FROM interaction_logs
// WHERE app_user_id = ?;
// `;
// results = await db.query(query, [req.user.id]);
// } else {
// console.log("Executing with last_created_at:", lastcreated_at);
// const query = `
// SELECT * FROM interaction_logs
// WHERE app_user_id = ?
// AND created_at > ?;
// `;
// results = await db.query(query, [req.user.id, lastcreated_at]);
// }
// if (results.length === 0) {
// return res.status(404).json({ message: 'No interaction logs found for this app user' });
// }
// res.status(200).json({
// message: 'Interaction logs fetched successfully',
// data: results,
// });
// } catch (error) {
// console.error('Error fetching interaction logs:', error.message);
// res.status(500).json({ error: 'Internal server error' });
// }
// }
// exports.checkEmailCode = async (req, res) => {
// try {
// const { email, hospital_code } = req.body;
// // Check if the email and code are provided
// if (!email || !hospital_code) {
// return res.status(400).json({ error: "Email and code are required" });
// }
// console.log("received data", email, hospital_code)
// // Check if the email exists in the database
// const useremail = await db.query("SELECT * FROM app_users WHERE email = ?", [email]);
// console.log("user email", useremail)
// if (useremail.length) {
// return res.status(404).json({ error: "Email already in use" });
// }
// // Check if the code is correct
// const usercode = await db.query("SELECT hospital_code FROM hospital_users WHERE hospital_code = ?", [hospital_code]);
// console.log("user code", usercode)
// if (!usercode.length) {
// return res.status(404).json({ error: "Please enter valid hospital code" });
// }
// // Code is correct, return success response
// res.status(200).json({ message: "Email code is correct" });
// } catch (error) {
// console.error("Error checking email code:", error);
// res.status(500).json({ error: "Internal server error" });
// }
// }
// // get popular topics
// exports.getPopularTopics = async (req, res) => {
// let popularTopics = [];
// try {
// // Fetch top 4 most viewed questions
// console.log("req.user data : ", req.user)
// const rows = await getMappedPopularQuestionsAnswers(req.user.hospital_code);
// if (!rows) {
// popularTopics = []
// }
// else {
// popularTopics = rows;
// }
// console.log('hospital data : ', rows)
// res.status(200).json({
// success: true,
// data: popularTopics
// });
// } catch (error) {
// console.error('Error fetching popular topics:', error);
// res.status(500).json({
// success: false,
// message: 'Internal server error'
// });
// }
// }
// const getMappedPopularQuestionsAnswers = async (hospitalCode) => {
// console.log("Hospital code is---", hospitalCode);
// try {
// const query = `
// SELECT il.query, il.response
// FROM interaction_logs il
// WHERE il.hospital_code = ?
// ORDER BY il.created_at DESC -- Sorting by most recent interactions
// LIMIT 10; -- Fetch more than 4 to filter unwanted entries
// `;
// const rows = await db.query(query, [hospitalCode]);
// console.log("Fetched questions before filtering:", rows);
// // Skip the row if either condition is true
// const filteredRows = rows.filter(row =>
// !(row.query.toLowerCase().includes("yes") || row.response.includes("Please reply with 'yes'"))
// );
// // Return only the top 4 filtered results
// return filteredRows.slice(0, 4);
// } catch (error) {
// console.error("Error fetching popular topics:", error.message);
// throw new Error("Internal server error");
// }
// };
// exports.changePin = async (req, res) => {
// try {
// const { current_pin, new_pin } = req.body;
// const userId = req.user.id;
// if (!current_pin || !new_pin) {
// return res.status(400).json({ error: "Current pin and new pin are required" });
// }
// // Add PIN length validation
// if (new_pin.length !== 4 || !/^\d+$/.test(new_pin)) {
// return res.status(400).json({ error: "New PIN must be exactly 4 digits" });
// }
// // Get user's current pin
// const userQuery = "SELECT pin_number FROM app_users WHERE id = ?";
// const user = await db.query(userQuery, [userId]);
// if (!user.length) {
// return res.status(404).json({ error: "User not found" });
// }
// // Verify current pin
// if (user[0].pin_number !== current_pin) {
// return res.status(400).json({ error: "Current pin is incorrect" });
// }
// // Check if new pin is same as current pin
// if (current_pin === new_pin) {
// return res.status(400).json({ error: "New PIN cannot be the same as current PIN" });
// }
// // Update to new pin
// await db.query(
// "UPDATE app_users SET pin_number = ? WHERE id = ?",
// [new_pin, userId]
// );
// res.json({ message: "Pin changed successfully" });
// } catch (error) {
// console.error("Error changing pin:", error);
// res.status(500).json({ error: "Internal server error" });
// }
// };
// exports.forgotPin = async (req, res) => {
// try {
// const { email } = req.body;
// if (!email) {
// return res.status(400).json({ error: "Email is required" });
// }
// // Get user details
// const userQuery = `
// SELECT au.id, au.username, au.pin_number, au.hospital_code, h.name_hospital
// FROM app_users au
// JOIN hospitals h ON au.hospital_code = h.hospital_code
// WHERE au.email = ?
// `;
// const user = await db.query(userQuery, [email]);
// if (!user.length) {
// return res.status(404).json({ error: "User not found" });
// }
// const userData = user[0];
// // Send pin via email
// const mailOptions = {
// from: "srikanth.mallikarjuna@tech4biz.io",
// to: email,
// subject: "Your Spurrinai PIN",
// html: `<!DOCTYPE html>
// <html lang="en">
// <head>
// <meta charset="UTF-8">
// <meta name="viewport" content="width=device-width, initial-scale=1.0">
// <title>Your PIN - Spurrinai Medical Platform</title>
// <style>
// @import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Syne:wght@400..800&display=swap');
// body {
// font-family: 'Inter', sans-serif;
// margin: 0;
// padding: 0;
// background-color: #ebf3fa;
// color: #333;
// }
// .email-container {
// max-width: 600px;
// margin: 20px auto;
// background: white;
// border-radius: 10px;
// overflow: hidden;
// box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
// }
// .email-header {
// background: linear-gradient(135deg, #2193b0, #6dd5ed);
// padding: 30px;
// text-align: center;
// color: white;
// }
// .hospital-name {
// display: inline-block;
// background-color: rgba(255, 255, 255, 0.2);
// padding: 5px 15px;
// border-radius: 20px;
// font-size: 14px;
// margin-bottom: 10px;
// }
// .email-content {
// padding: 40px 30px;
// }
// .greeting {
// font-size: 30px;
// font-weight: 700;
// margin-bottom: 20px;
// color: #303030;
// }
// .pin-display {
// background-color: #f5f9fc;
// border: 1px solid #e0e9f0;
// border-radius: 8px;
// padding: 20px;
// margin: 25px 0;
// text-align: center;
// }
// .pin {
// font-family: 'Courier New', monospace;
// font-size: 32px;
// letter-spacing: 6px;
// color: #2193b0;
// font-weight: bold;
// padding: 10px 0;
// }
// .security-note {
// margin-top: 30px;
// padding-top: 20px;
// border-top: 1px solid #eee;
// font-size: 14px;
// color: #666;
// }
// .email-footer {
// background-color: #f5f9fc;
// padding: 20px;
// text-align: center;
// font-size: 13px;
// color: #888;
// border-top: 1px solid #e0e9f0;
// }
// </style>
// </head>
// <body>
// <div class="email-container">
// <div class="email-header">
// <div class="hospital-name">${userData.name_hospital}</div>
// <h1>Your PIN Information</h1>
// </div>
// <div class="email-content">
// <div class="greeting">Hello ${userData.username},</div>
// <p>Here is your PIN for the Spurrinai healthcare platform:</p>
// <div class="pin-display">
// <div class="pin">${userData.pin_number}</div>
// </div>
// <div class="security-note">
// <p>For security reasons, please do not share this PIN with anyone. If you did not request this information, please contact our support team immediately.</p>
// </div>
// </div>
// <div class="email-footer">
// <p>© 2025 Spurrinai - Healthcare Data Management Platform</p>
// <p>This is an automated message. Please do not reply to this email.</p>
// <p>Need help? Contact <a href="mailto:support@spurrinai.com">support@spurrinai.com</a></p>
// </div>
// </div>
// </body>
// </html>`
// };
// await transporter.sendMail(mailOptions);
// res.json({ message: "PIN has been sent to your email" });
// } catch (error) {
// console.error("Error in forgot pin:", error);
// res.status(500).json({ error: "Internal server error" });
// }
// };