const pool = require("../config/dbConnect");

class User {
  constructor(
    nomor_induk,
    nama,
    jenis_kelamin,
    semester,
    program_studi,
    fakultas,
    alamat,
    email,
    no_telpon,
    password,
    foto,
    role,
    code,
    kuota
  ) {
    this._nomor_induk = nomor_induk;
    this._nama = nama;
    this._jenis_kelamin = jenis_kelamin;
    this._semester = semester;
    this._program_studi = program_studi;
    this._fakultas = fakultas;
    this._alamat = alamat;
    this._email = email;
    this._no_telpon = no_telpon;
    this._password = password;
    this._foto = foto;
    this._role = role;
    this._code = code;
    this._kuota = kuota;
  }

  get nomor_induk() {
    return this._nomor_induk;
  }

  set nomor_induk(nomor_induk) {
    if (!nomor_induk) throw new Error("Invalid nomor_induk value.");

    nomor_induk = nomor_induk.trim();
    if (nomor_induk === "") throw new Error("Invalid nomor_induk value.");

    this._nomor_induk = nomor_induk;
  }

  get nama() {
    return this._nama;
  }

  set nama(nama) {
    if (!nama) throw new Error("Invalid nama value.");

    nama = nama.trim();
    if (nama === "") throw new Error("Invalid nama value.");

    this._nama = nama;
  }

  get jenis_kelamin() {
    return this._jenis_kelamin;
  }

  set jenis_kelamin(jenis_kelamin) {
    if (!jenis_kelamin) throw new Error("Invalid jenis_kelamin value.");

    jenis_kelamin = jenis_kelamin.trim();
    if (jenis_kelamin === "") throw new Error("Invalid jenis_kelamin value.");

    this._jenis_kelamin = jenis_kelamin;
  }

  get semester() {
    return this._semester;
  }

  set semester(semester) {
    if (!semester) throw new Error("Invalid semester value.");

    semester = semester.trim();
    if (semester === "") throw new Error("Invalid semester value.");

    this._semester = semester;
  }

  get program_studi() {
    return this._program_studi;
  }

  set program_studi(program_studi) {
    if (!program_studi) throw new Error("Invalid program_studi value.");

    program_studi = program_studi.trim();
    if (program_studi === "") throw new Error("Invalid program_studi value.");

    this._program_studi = program_studi;
  }

  get fakultas() {
    return this._fakultas;
  }

  set fakultas(fakultas) {
    if (!fakultas) throw new Error("Invalid fakultas value.");

    fakultas = fakultas.trim();
    if (fakultas === "") throw new Error("Invalid fakultas value.");

    this._fakultas = fakultas;
  }

  get alamat() {
    return this._alamat;
  }

  set alamat(alamat) {
    if (!alamat) throw new Error("Invalid alamat value.");

    alamat = alamat.trim();
    if (alamat === "") throw new Error("Invalid alamat value.");

    this._alamat = alamat;
  }

  get email() {
    return this._email;
  }

  set email(email) {
    if (!email) throw new Error("Invalid email value.");

    email = email.trim();
    if (email === "") throw new Error("Invalid email value.");

    this._email = email;
  }

  get no_telpon() {
    return this._no_telpon;
  }

  set no_telpon(no_telpon) {
    if (!no_telpon) throw new Error("Invalid no_telpon value.");

    no_telpon = no_telpon.trim();
    if (no_telpon === "") throw new Error("Invalid no_telpon value.");

    this._no_telpon = no_telpon;
  }

  get password() {
    return this._password;
  }

  set password(password) {
    if (!password) throw new Error("Invalid password value.");

    password = password.trim();
    if (password === "") throw new Error("Invalid password value.");

    this._password = password;
  }

  get foto() {
    return this._foto;
  }

  set foto(foto) {
    if (!foto) throw new Error("Invalid foto value.");

    foto = foto.trim();
    if (foto === "") throw new Error("Invalid foto value.");

    this._foto = foto;
  }

  get role() {
    return this._role;
  }

  set role(role) {
    if (!role) throw new Error("Invalid role value.");

    role = role.trim();
    if (role === "") throw new Error("Invalid role value.");

    this._role = role;
  }

  get code() {
    return this._code;
  }

  set code(code) {
    if (!code) throw new Error("Invalid code value.");

    this._code = code;
  }

  get kuota() {
    return this._kuota;
  }

  set kuota(kuota) {
    if (!kuota) throw new Error("Invalid kuota value.");

    kuota = kuota.trim();
    if (kuota === "") throw new Error("Invalid kuota value.");

    this._kuota = kuota;
  }

  async save() {
    const sql = `INSERT INTO users (nomor_induk, nama, jenis_kelamin, semester, program_studi, fakultas, alamat, email, no_telpon, password, foto, role, code, kuota) VALUES ("${this.nomor_induk}", "${this.nama}", "${this.jenis_kelamin}", "${this.semester}", "${this.program_studi}", "${this.fakultas}", "${this.alamat}", "${this.email}", "${this.no_telpon}", "${this.password}", "${this.foto}", "${this.role}", '${JSON.stringify(this.code)}', "${this.kuota}")`;
    await pool.execute(sql);
  }

  static async find() {
    const sql = "SELECT * FROM users";
    const [rows, fields] = await pool.execute(sql);

    return rows;
  }

  static async findById(nomorInduk) {
    const sql = `SELECT * FROM users WHERE nomor_induk = ${nomorInduk}`;
    const [rows, fields] = await pool.execute(sql);

    return rows[0];
  }

  static async findByRole(role) {
    const sql = `SELECT * FROM users WHERE role = ${role}`;
    const [rows, fields] = await pool.execute(sql);

    return rows;
  }

  static async findByIdAndUpdate(nomor_induk, options) {
    const sql = `UPDATE users SET nomor_induk = "${options.nomor_induk}", nama = "${options.nama}", jenis_kelamin = "${options.jenis_kelamin}", semester = "${options.semester}", program_studi = "${options.program_studi}", fakultas = "${options.fakultas}", alamat = "${options.alamat}", email = "${options.email}", no_telpon = "${options.no_telpon}", password = "${options.password}", foto = "${options.foto}", role = "${options.role}", code = '${JSON.stringify(options.code)}', kuota = "${options.kuota}" WHERE nomor_induk = "${nomor_induk}"`;
    await pool.execute(sql);
  }

  static async findByIdAndDelete(nomor_induk) {
    const sql = `DELETE FROM users WHERE nomor_induk = "${nomor_induk}"`;
    await pool.execute(sql);
  }
}

module.exports = User;
