const mysql = require("mysql");

function getConnection() {
  return mysql.createConnection({
    host: process.env.MYSQL_HOST,
    user: process.env.MYSQL_USER,
    password: process.env.MYSQL_PASSWORD,
    database: process.env.MYSQL_DATABASE,
  });
}

function getUsers(connection) {
  return new Promise((resolve, reject) => {
    connection.query(
      `SELECT id, username, admin FROM users`,
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function getUser(connection, id) {
  return new Promise((resolve, reject) => {
    connection.query(
      `SELECT * FROM users WHERE id = ?`,
      [id], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function searchUser(connection, search) {
  return new Promise((resolve, reject) => {
    connection.query(
      `SELECT * FROM users WHERE username LIKE ? LIMIT 5`,
      [`%${search}%`], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function getUserByUsername(connection, username) {
  return new Promise((resolve, reject) => {
    connection.query(
      `SELECT * FROM users WHERE username = ?`,
      [username], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function addUser(connection, username, password) {
  return new Promise((resolve, reject) => {
    connection.query(
      `INSERT INTO users (username, password) VALUES (?, ?)`,
      [username, password], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function getUserLastMessages(connection, username) {
  return new Promise((resolve, reject) => {
    connection.query(
      `SELECT messages.id, user_id, username, content, date, channels.name AS channel_name 
       FROM messages 
       JOIN users ON messages.user_id = users.id 
       JOIN channels ON messages.channel_id = channels.id 
       WHERE username = ? 
       ORDER BY date DESC LIMIT 5`,
      [username], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function deleteUser(connection, id) {
  return new Promise((resolve, reject) => {
    connection.query(
      `DELETE FROM users WHERE id = ?`,
      [id], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
};

function getChannels(connection) {
  return new Promise((resolve, reject) => {
    connection.query(
      `SELECT * FROM channels`,
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function getActiveChannels(connection) {
  return new Promise((resolve, reject) => {
    connection.query(
      `SELECT channels.id, name, description, owner_id, username AS owner_username, count(*) AS message_count
       FROM messages
       JOIN channels ON messages.channel_id = channels.id
       JOIN users ON messages.user_id = users.id
       WHERE date > (SELECT max(date) FROM messages) - 3 * 24 * 60 * 60
       GROUP BY channel_id
       ORDER BY count(*) DESC
       LIMIT 5;`,
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function getNewChannels(connection) {
  return new Promise((resolve, reject) => {
    connection.query(
      `SELECT channels.id, name, description, owner_id, username AS owner_username 
       FROM channels 
       JOIN users ON channels.owner_id = users.id 
       ORDER BY channels.id DESC LIMIT 5`,
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function searchChannels(connection, search) {
  return new Promise((resolve, reject) => {
    connection.query(
      `SELECT channels.id, name, description, owner_id, username AS owner_username 
       FROM channels 
       JOIN users ON channels.owner_id = users.id 
       WHERE name LIKE ?
       LIMIT 5`,
      [`%${search}%`], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function getChannel(connection, name) {
  return new Promise((resolve, reject) => {
    connection.query(
      `SELECT channels.id, name, description, owner_id, username AS owner_username 
       FROM channels 
       JOIN users ON channels.owner_id = users.id 
       WHERE name = ?`,
      [name], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function addChannel(connection, name, description, owner_id) {
  return new Promise((resolve, reject) => {
    connection.query(
      `INSERT INTO channels (name, description, owner_id) VALUES (?, ?, ?)`,
      [name, description, owner_id], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function deleteChannel(connection, channel_id) {
  return new Promise((resolve, reject) => {
    connection.query(
      `DELETE FROM channels WHERE id = ?`,
      [channel_id], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function getMessages(connection, channel_id) {
  return new Promise((resolve, reject) => {
    connection.query(
      `SELECT messages.id, user_id, username, content, date, channels.name AS channel_name 
       FROM messages 
       JOIN users ON messages.user_id = users.id 
       JOIN channels ON messages.channel_id = channels.id 
       WHERE channel_id = ? 
       ORDER BY date DESC`,
      [channel_id], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function getLastMessages(connection) {
  return new Promise((resolve, reject) => {
    connection.query(
      `SELECT messages.id, user_id, username, content, date, channels.name AS channel_name 
       FROM messages 
       JOIN users ON messages.user_id = users.id 
       JOIN channels ON messages.channel_id = channels.id 
       ORDER BY date DESC LIMIT 5`,
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function getMessage(connection, message_id) {
  return new Promise((resolve, reject) => {
    connection.query(
      `SELECT messages.id, user_id, username, content, date, channels.name AS channel_name 
       FROM messages 
       JOIN users ON messages.user_id = users.id 
       JOIN channels ON messages.channel_id = channels.id 
       WHERE messages.id = ?`,
      [message_id], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function addMessage(connection, channel_id, user_id, message) {
  return new Promise((resolve, reject) => {
    connection.query(
      `INSERT INTO messages (channel_id, user_id, content, date) VALUES (?, ?, ?, ?)`,
      [channel_id, user_id, message, Math.floor(Date.now() / 1000)], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function deleteMessage(connection, message_id) {
  return new Promise((resolve, reject) => {
    connection.query(
      `DELETE FROM messages WHERE id = ?`,
      [message_id], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function deleteChannelMessages(connection, channel_id) {
  return new Promise((resolve, reject) => {
    connection.query(
      `DELETE FROM messages WHERE channel_id = ?`,
      [channel_id], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function deleteUserMessages(connection, user_id) {
  return new Promise((resolve, reject) => {
    connection.query(
      `DELETE FROM messages WHERE user_id = ?`,
      [user_id], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function addMention(connection, message_id, user_id) {
  return new Promise((resolve, reject) => {
    connection.query(
      `INSERT INTO mentions (message_id, user_id) VALUES (?, ?)`,
      [message_id, user_id], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function getMentions(connection, message_id) {
  return new Promise((resolve, reject) => {
    connection.query(
      `SELECT users.username FROM mentions 
       JOIN users ON mentions.user_id = users.id 
       WHERE message_id = ?`,
      [message_id], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function deleMentions(connection, message_id) {
  return new Promise((resolve, reject) => {
    connection.query(
      `DELETE FROM mentions WHERE message_id = ?`,
      [message_id], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function deleteChannelMentions(connection, channel_id) {
  return new Promise((resolve, reject) => {
    connection.query(
      `DELETE FROM mentions WHERE message_id IN 
       (SELECT id FROM messages WHERE channel_id = ?)`,
      [channel_id], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

function deleteUserMentions(connection, user_id) {
  return new Promise((resolve, reject) => {
    connection.query(
      `DELETE FROM mentions WHERE user_id = ?`,
      [user_id], // Use parameterized query
      (error, result) => {
        if (error) {
          reject(new Error(error));
        }
        resolve(result);
      }
    );
  });
}

module.exports = {
  getUsers,
  getConnection,
  getUser,
  searchUser,
  getUserByUsername,
  addUser,
  deleteUser,
  getUserLastMessages,
  getChannels,
  getActiveChannels,
  getNewChannels,
  searchChannels,
  getChannel,
  addChannel,
  deleteChannel,
  getMessages,
  getLastMessages,
  getMessage,
  addMessage,
  deleteMessage,
  deleteChannelMessages,
  deleteUserMessages,
  addMention,
  getMentions,
  deleMentions,
  deleteUserMentions,
  deleteChannelMentions,
};
