const { pool } = require('../database')
const { matiereSysteme } = require('../function/System')

/**
 * function uset to create matiere
 * @param {*} nom
 * @returns Promise
 */
async function createMatiere(nom, credit, uniter, ue) {
  const sql =
    'INSERT INTO matieres (nom, unite_enseignement, credit, heure, ue) VALUES (?, ?, ?, ?, ?)'

  const uniterHeure = 'SELECT uniter_heure FROM nessesaryTable'
  let [rows] = await pool.query(uniterHeure)
  const uniterHeureValue = rows[0].uniter_heure
  const heure = credit * uniterHeureValue
  try {
    const [result] = await pool.query(sql, [nom, uniter, credit, heure, ue])

    return {
      success: true,
      id: result.insertId
    }
  } catch (error) {
    return { success: false, error: 'Erreur veullez réeseyer' + error }
  }
}

/**
 * function to get all matieres
 * @returns Promise
 */
async function getMatiere() {
  const sql = 'SELECT m.*, n.nom AS niveau_nom FROM matieres m LEFT JOIN niveaus n ON m.niveau_id = n.id ORDER BY m.id DESC'

  try {
    let [rows] = await pool.query(sql)

    return rows
  } catch (error) {
    return { success: false, error: 'Erreur veullez réeseyer' + error }
  }
}
async function displayMatiereFromForm(niveau, mention_id, parcours) {
  console.log('modele: ',niveau,mention_id,parcours);
  let semestre = await matiereSysteme(niveau);
  console.log(semestre);
  if (!semestre || semestre.length < 2) {
    console.error('Semestre insuffisant pour', niveau);
    return [];
  }

  let sql, params;

  if (niveau !== 'L1') {
    sql = `
      SELECT DISTINCT m.*
      FROM matieres m
      JOIN matiere_semestre ms ON m.id = ms.matiere_id
      JOIN semestres s ON ms.semestre_id = s.id
      JOIN parcoursmatiere pm ON m.id = pm.matiere_id
      JOIN parcours p ON pm.parcour_id = p.id
      WHERE (s.nom LIKE ? OR s.nom LIKE ?)
        AND ms.mention_id = ?
        AND p.nom LIKE ?
    `;
    params = [`%${semestre[0]}%`, `%${semestre[1]}%`, mention_id, `%${parcours}%`];
  } else {
    sql = `
      SELECT DISTINCT m.*
      FROM matieres m
      JOIN matiere_semestre ms ON m.id = ms.matiere_id
      JOIN semestres s ON ms.semestre_id = s.id
      WHERE (s.nom LIKE ? OR s.nom LIKE ?)
        AND ms.mention_id = ?
    `;
    params = [`%${semestre[0]}%`, `%${semestre[1]}%`, mention_id];
  }

  try {
    const [rows] = await pool.query(sql, params);
    return rows;
  } catch (error) {
    console.error(error);
    return [];
  }
}


/**
 * function to get single matiere
 * @param {*} id
 * @returns promise
 */
async function getSingleMatiere(id) {
  const sql = 'SELECT * FROM matieres WHERE id = ?'

  try {
    let [rows] = await pool.query(sql, [id])

    return rows[0]
  } catch (error) {
    return { success: false, error: 'Erreur veullez réeseyer' + error }
  }
}

/**
 * function used when updating matiere
 * @param {*} nom
 * @param {*} id
 * @returns promise
 */
async function updateMatiere(nom, id, credit, uniter, ue) {
  const sql =
    'UPDATE matieres SET nom = ?, credit = ?, unite_enseignement = ?, heure = ?, ue = ? WHERE id = ?'

  const uniterHeure = 'SELECT uniter_heure FROM nessesaryTable'
  let [rows] = await pool.query(uniterHeure)
  const uniterHeureValue = rows[0].uniter_heure
  const heure = credit * uniterHeureValue

  try {
    let [result] = await pool.query(sql, [nom, credit, uniter, heure, ue, id])

    if (result.affectedRows === 0) {
      return {
        success: false,
        message: 'Année Univesitaire non trouvé ou aucune modification effectuée.'
      }
    }

    return {
      success: true,
      message: 'Année Univesitaire mis à jour avec succès.'
    }
  } catch (error) {
    return { success: false, error: 'Erreur veullez réeseyer' + error }
  }
}
async function updateMatiereNiveau(formData) {
  const { niveau_id, id } = formData; // ici id sera bien défini
  const sql = 'UPDATE matieres SET niveau_id = ? WHERE id = ?';

  try {
    const [result] = await pool.query(sql, [niveau_id, id]);

    if (result.affectedRows === 0) {
      return {
        success: false,
        message: `Matière avec id ${id} non trouvée ou niveau déjà attribué.`
      };
    }

    return {
      success: true,
      message: `Niveau de la matière ${id} mis à jour avec succès.`
    };
  } catch (error) {
    return {
      success: false,
      error: 'Erreur lors de la mise à jour : ' + error.message
    };
  }
}

async function deleteMatiere(id) {
  const sql = 'DELETE FROM matieres WHERE id = ?';

  try {
    let [result] = await pool.query(sql, [id]);

    if (result.affectedRows === 0) {
      return {
        success: false,
        message: 'Matière non trouvée.'
      };
    }

    return {
      success: true,
      message: 'Matière supprimée avec succès.'
    };
  } catch (error) {
    console.log("err: ",+ error)
    return { success: false, error: 'Erreur, veuillez réessayer: ' + error };
    
  }
}


/**
 * Assign mentions to a matiere
 * @param {Object} formData - keys = mention_ids, values = true/false
 * @param {number} id - matiere_id
 */
async function asygnationToMention(formData, id) {
  const selectedKeys = Object.keys(formData).filter((key) => formData[key])

  if (selectedKeys.length === 0) {
    return { success: false, error: 'No mentions selected.' }
  }

  // build placeholders like (?, ?, ?)
  const placeholders = selectedKeys.map(() => '?').join(',')

  const deleteMentionSql = `
    DELETE FROM matiere_mention
    WHERE matiere_id = ?
  `

  const deleteSemestreMentionSql = `
    DELETE FROM matiere_semestre
    WHERE matiere_id = ?
    AND mention_id NOT IN (${placeholders})
  `

  const deleteNotesSql = `
    DELETE FROM notes
    WHERE matiere_id = ?
    AND mention_id NOT IN (${placeholders})
  `

  const insertMentionSql = `
    INSERT INTO matiere_mention (matiere_id, mention_id)
    VALUES (?, ?)
  `

  try {
    const connection = await pool.getConnection()
    try {
      await connection.beginTransaction()

      // delete all from matiere_mention for this matiere
      await connection.query(deleteMentionSql, [id])

      // delete from matiere_semestre not in selected mentions
      await connection.query(deleteSemestreMentionSql, [id, ...selectedKeys])

      // delete from notes not in selected mentions
      await connection.query(deleteNotesSql, [id, ...selectedKeys])

      // re-insert new mentions
      for (const mentionId of selectedKeys) {
        await connection.query(insertMentionSql, [id, mentionId])
      }

      await connection.commit()

      return { success: true }
    } catch (error) {
      await connection.rollback()
      console.error(error)
      return { success: false, error: error.message }
    } finally {
      connection.release()
    }
  } catch (connErr) {
    console.error(connErr)
    return { success: false, error: 'Database connection error.' }
  }
}

async function getMentionMatiere(id) {
  const sql = 'SELECT * FROM matiere_mention WHERE matiere_id = ?'

  try {
    let [rows] = await pool.query(sql, [id])

    return rows
  } catch (error) {
    return error
  }
}

async function getMentionMatiereChecked(matiere_id) {
  const getMentionMatiere = 'SELECT * FROM matiere_mention WHERE matiere_id = ?'
  let [rows] = await pool.query(getMentionMatiere, [matiere_id])
  let MentionArray = rows
  let arrayID = []

  for (let index = 0; index < MentionArray.length; index++) {
    arrayID.push(MentionArray[index].mention_id)
  }

  const mentionQuery = `SELECT * FROM mentions WHERE id IN (${arrayID.map(() => '?').join(', ')})`

  try {
    let [rows] = await pool.query(mentionQuery, [...arrayID])

    return rows
  } catch (error) {
    return error
  }
}

async function getSemestreMatiere(id) {
  const sql = 'SELECT * FROM matiere_semestre WHERE matiere_id = ?'

  try {
    let [rows] = await pool.query(sql, [id])

    return rows
  } catch (error) {
    return error
  }
}

async function getSemestre() {
  const sql = 'SELECT * FROM semestres'

  try {
    let [rows] = await pool.query(sql)

    return rows
  } catch (error) {
    return error
  }
}

async function insertUpdateMentionSemestre(matiere_id, formData) {
  try {
    const connection = await pool.getConnection()

    try {
      await connection.beginTransaction()

      // Clear all old rows
      const deleteSql = `
        DELETE FROM matiere_semestre
        WHERE matiere_id = ?
      `
      await connection.query(deleteSql, [matiere_id])

      // Prepare INSERT
      const insertSql = `
        INSERT INTO matiere_semestre (matiere_id, semestre_id, mention_id)
        VALUES (?, ?, ?)
      `

      // Insert new rows
      for (const mention_id of Object.keys(formData)) {
        for (const semestre_id of formData[mention_id]) {
          await connection.query(insertSql, [matiere_id, semestre_id, mention_id])
        }
      }

      await connection.commit()

      return { success: true }
    } catch (err) {
      await connection.rollback()
      console.error(err)
      return { success: false, error: err.message }
    } finally {
      connection.release()
    }
  } catch (err) {
    console.error(err)
    return { success: false, error: 'Database connection failed.' }
  }
}

async function getEnseignants() {
  try {
    const latestIdsSql = `
      SELECT MAX(id) AS id
      FROM matiereEnseignants
      GROUP BY matiere_id
      ORDER BY MAX(date) DESC
    `

    const [rows] = await pool.query(latestIdsSql)

    const latestIds = rows.map((r) => r.id)

    if (latestIds.length === 0) {
      return []
    }

    // Build placeholders (?, ?, ?, …)
    const placeholders = latestIds.map(() => `?`).join(`,`)
    const fetchSql = `
      SELECT *
      FROM matiereEnseignants
      WHERE id IN (${placeholders})
    `

    const [enseignants] = await pool.query(fetchSql, latestIds)

    return enseignants
  } catch (error) {
    console.error(error)
    return error
  }
}

async function insertNewProf(matiere_id, nom, prenom, contact, date) {
  const sql = `
    INSERT INTO matiereEnseignants
      (matiere_id, nom_enseignant, prenom_enseignant, contact, date)
    VALUES (?, ?, ?, ?, ?)
  `

  try {
    const [result] = await pool.query(sql, [matiere_id, nom, prenom, contact, date])

    return {
      success: true,
      id: result.insertId
    }
  } catch (error) {
    console.error(error)
    return error
  }
}

async function getSIngleProf(matiere_id) {
  const sql = `
    SELECT *
    FROM matiereEnseignants
    WHERE matiere_id = ?
    ORDER BY date DESC
    LIMIT 1
  `

  try {
    const [rows] = await pool.query(sql, [matiere_id])
    return rows[0] || null
  } catch (error) {
    console.error(error)
    return error
  }
}

async function updateProf(matiere_id, nom, prenom, contact, date) {
  const sql = `
    UPDATE matiereEnseignants
    SET nom_enseignant = ?,
        prenom_enseignant = ?,
        contact = ?,
        date = ?
    WHERE matiere_id = ?
  `

  try {
    const [result] = await pool.query(sql, [nom, prenom, contact, date, matiere_id])

    if (result.affectedRows === 0) {
      return {
        success: false,
        message: 'Année Univesitaire non trouvé.'
      }
    }

    return {
      success: true,
      message: 'Année Univesitaire supprimé avec succès.'
    }
  } catch (error) {
    console.error(error)
    return error
  }
}

module.exports = {
  createMatiere,
  getSIngleProf,
  getMatiere,
  getSingleMatiere,
  updateMatiere,
  updateMatiereNiveau,
  displayMatiereFromForm,
  deleteMatiere,
  asygnationToMention,
  getMentionMatiere,
  getMentionMatiereChecked,
  getSemestreMatiere,
  getSemestre,
  insertUpdateMentionSemestre,
  getEnseignants,
  insertNewProf,
  updateProf
}
