const AbstractManager = require("./AbstractManager");

class UserManager extends AbstractManager {
  constructor() {
    super({ table: "users" });
  }

  // The C of CRUD - Create operation
  async create(user) {
    const { nickname, mail, tetardcoin, password, firstname, lastname } = user;

    const [result] = await this.database.query(
      `INSERT INTO ${this.table} (nickname, mail, tetardcoin, password, firstname, lastname) VALUES (?, ?, ?, ?, ?, ?)`,
      [nickname, mail, tetardcoin, password, firstname ?? null, lastname ?? null]
    );

    return result.insertId;
  }

  async getBySuperOAuthId(superOAuthId) {
    const [rows] = await this.database.query(
      `SELECT * FROM ${this.table} WHERE super_oauth_id = ?`,
      [superOAuthId]
    );
    return rows[0] ?? null;
  }

  async linkSuperOAuth(id, superOAuthId) {
    const [result] = await this.database.query(
      `UPDATE ${this.table} SET super_oauth_id = ? WHERE id = ?`,
      [superOAuthId, id]
    );
    return result.affectedRows;
  }

  // The Rs of CRUD - Read operations
  async read(id, field) {
    if (field) {
      const [rows] = await this.database.query(
        `SELECT ?? FROM ${this.table} WHERE id = ?`,
        [field, id]
      );

      if (rows.length === 0) {
        return null;
      }

      return rows[0][field];
    }

    const [rows] = await this.database.query(
      `SELECT * FROM ${this.table} WHERE id = ?`,
      [id]
    );

    if (rows.length === 0) {
      return null;
    }

    return rows[0];
  }

  async getByMail(mail) {
    const [rows] = await this.database.query(
      `SELECT * FROM ${this.table} WHERE mail = ?`,
      [mail]
    );

    if (rows.length === 0) {
      return null;
    }

    return rows[0];
  }

  async readAll() {
    const [rows] = await this.database.query(`SELECT * FROM ${this.table}`);
    return rows;
  }

  // The U of CRUD - Update operation
  async edit(id, updatedFields) {
    const allowedFields = [
      "mail",
      "nickname",
      "tetardcoin",
      "password",
      "firstname",
      "lastname",
    ];

    const fieldsToUpdate = Object.keys(updatedFields).filter((field) =>
      allowedFields.includes(field)
    );

    const updateValues = fieldsToUpdate.map((field) => updatedFields[field]);

    if (fieldsToUpdate.length === 0) {
      return 0;
    }

    const updateQuery = `UPDATE ${this.table} SET ${fieldsToUpdate
      .map((field) => `${field} = ?`)
      .join(", ")} WHERE id = ?`;

    updateValues.push(id);

    const [result] = await this.database.query(updateQuery, updateValues);

    return result.affectedRows;
  }

  // The D of CRUD - Delete operation
  async delete(id) {
    await this.database.query(`DELETE FROM ${this.table} WHERE id = ?`, [id]);
  }
}

module.exports = UserManager;
