const { pool } = require('../database')
const dayjs = require('dayjs')

async function updateCurrentYears() {
  const fullDate = dayjs().format('YYYY-MM-DD')

  // Clear current year flag
  const clearCurrent = 'UPDATE anneescolaire SET is_Current = 0 WHERE id > 0'
  pool.query(clearCurrent)

  // Set the new current year
  const updateCurrent = `
    UPDATE anneescolaire
    SET is_Current = 1
    WHERE ? >= debut AND ? <= fin
  `
  // console.log();
  pool.query(updateCurrent, [fullDate, fullDate])

  // Check if the update was successful
  const sql = `
      SELECT * FROM anneescolaire
      WHERE ? >= debut AND ? <= fin
    `
  const [rows] = await pool.query(sql, [fullDate, fullDate])

  const check = rows[0]
  if (!check) return

  // 2. Check if already in traitmentsystem
  const searchSql = `SELECT * FROM traitmentsystem WHERE code = ?`
  const [searchRows] = await pool.query(searchSql, [check.code])

  if (searchRows.length === 0) {
    // 3. Insert into traitmentsystem
    const insertSql = `
        INSERT INTO traitmentsystem (code, debut, fin)
        VALUES (?, ?, ?)
      `
    await pool.query(insertSql, [check.code, check.debut, check.fin])
  } else {
    console.log('No active school year found for the current date.')
  }
}

// Helper functions (unchanged)
function checkNull(params) {
  if (params === null || params === undefined) return null
  return params
}
function compareSessionNotes(session1, session2) {
  if (session2) {
    return session1 < session2.note ? session2.note : session1
  }
  return session1
}
function nextLevel(niveau) {
  const levels = ['L1', 'L2', 'L3', 'M1', 'M2', 'D1', 'D2', 'D3', 'PHD']
  const idx = levels.indexOf(niveau)
  return idx === -1 || idx === levels.length - 1 ? niveau : levels[idx + 1]
}
function updateSchoolYear(year) {
  const [startYear, endYear] = year.split('-').map(Number)
  return `${startYear + 1}-${endYear + 1}`
}

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

    // Get unfinished years (only one record assumed)
    const [unfinishedYearsRows] = await connection.query(
      'SELECT * FROM traitmentsystem WHERE is_finished = 0 ORDER BY id ASC LIMIT 1'
    )
    if (unfinishedYearsRows.length === 0) {
      await connection.release()
      return { message: 'No unfinished years found.' }
    }
    const unfinishedYear = unfinishedYearsRows[0]

    // Get all students of that unfinished year
    const [allEtudiants] = await connection.query(
      'SELECT * FROM etudiants WHERE annee_scolaire = ?',
      [unfinishedYear.code]
    )

    // Get distinct student IDs with notes
    let etudiantWithNotes = []
    for (const etudiant of allEtudiants) {
      const [results] = await connection.query(
        'SELECT DISTINCT etudiant_id FROM notes WHERE etudiant_niveau = ? AND annee_scolaire = ?',
        [etudiant.niveau, etudiant.annee_scolaire]
      )
      etudiantWithNotes.push(...results)
    }
    // Unique IDs
    const uniqueId = [
      ...new Map(etudiantWithNotes.map((item) => [item.etudiant_id, item])).values()
    ]

    // Get notes details per student
    let allEtudiantWithNotes = []
    for (const student of uniqueId) {
      const [rows] = await connection.query(
        `SELECT notes.*, etudiants.*, matieres.id, matieres.nom AS nomMat, matieres.credit
         FROM notes
         LEFT JOIN etudiants ON notes.etudiant_id = etudiants.id
         LEFT JOIN matieres ON notes.matiere_id = matieres.id
         WHERE notes.etudiant_id = ?`,
        [student.etudiant_id]
      )
      allEtudiantWithNotes.push(rows)
    }

    // Get distinct student IDs with notesrepech
    let etudiantWithNotesRepech = []
    for (const etudiant of allEtudiants) {
      const [results] = await connection.query(
        'SELECT DISTINCT etudiant_id FROM notesrepech WHERE etudiant_niveau = ? AND annee_scolaire = ?',
        [etudiant.niveau, etudiant.annee_scolaire]
      )
      etudiantWithNotesRepech.push(...results)
    }
    // Unique IDs for repech
    const uniqueIdRepech = [
      ...new Map(etudiantWithNotesRepech.map((item) => [item.etudiant_id, item])).values()
    ]

    // Get notesrepech details per student
    let allEtudiantWithNotesRepech = []
    for (const student of uniqueIdRepech) {
      const [rows] = await connection.query(
        `SELECT notesrepech.*, etudiants.*, matieres.id, matieres.nom AS nomMat, matieres.credit
         FROM notesrepech
         INNER JOIN etudiants ON notesrepech.etudiant_id = etudiants.id
         INNER JOIN matieres ON notesrepech.matiere_id = matieres.id
         WHERE notesrepech.etudiant_id = ?`,
        [student.etudiant_id]
      )
      allEtudiantWithNotesRepech.push(rows)
    }

    // Compute averages and prepare data
    let dataToMap = []
    for (let i = 0; i < allEtudiantWithNotes.length; i++) {
      const notesNormal = allEtudiantWithNotes[i]
      const notesRepech = allEtudiantWithNotesRepech[i] || []

      let total = 0
      let totalCredit = 0
      let modelJson = {
        id: '',
        nom: '',
        prenom: '',
        photos: '',
        moyenne: '',
        mention: '',
        niveau: '',
        annee_scolaire: ''
      }

      for (let j = 0; j < notesNormal.length; j++) {
        const normalNote = notesNormal[j]
        modelJson.id = normalNote.etudiant_id
        modelJson.nom = normalNote.nom
        modelJson.prenom = normalNote.prenom
        modelJson.photos = normalNote.photos
        modelJson.mention = normalNote.mention_id
        modelJson.niveau = normalNote.niveau
        modelJson.annee_scolaire = normalNote.annee_scolaire

        // Find repech note for same matiere if exists
        const repechNoteObj = notesRepech.find((r) => r.matiere_id === normalNote.matiere_id)
        const noteToUse = compareSessionNotes(normalNote.note, checkNull(repechNoteObj))

        total += (noteToUse ?? 0) * normalNote.credit
        totalCredit += normalNote.credit
      }

      modelJson.moyenne = (totalCredit > 0 ? total / totalCredit : 0).toFixed(2)
      dataToMap.push(modelJson)
    }

    // Get note system thresholds
    const [noteSystemRows] = await connection.query('SELECT * FROM notesystems LIMIT 1')
    const noteSystem = noteSystemRows[0]

    // Update etudiants based on moyenne
    for (const student of dataToMap) {
      let status, newNiveau, newAnnee
      newAnnee = updateSchoolYear(student.annee_scolaire)

      if (student.moyenne >= noteSystem.admis) {
        newNiveau = nextLevel(student.niveau)
        status = 2 // Passed
      } else if (student.moyenne >= noteSystem.redouble) {
        newNiveau = student.niveau
        status = 3 // Repeat
      } else {
        newNiveau = student.niveau
        status = 4 // Fail
      }

      await connection.query(
        'UPDATE etudiants SET niveau = ?, annee_scolaire = ?, status = ? WHERE id = ?',
        [newNiveau, newAnnee, status, student.id]
      )
    }

    // Mark unfinished year as finished
    await connection.query('UPDATE traitmentsystem SET is_finished = 1 WHERE id = ?', [
      unfinishedYear.id
    ])

    await connection.commit()
    connection.release()

    return { success: true, message: 'Students updated successfully' }
  } catch (error) {
    await connection.rollback()
    connection.release()
    console.error(error)
    throw error
  }
}

async function matiereSysteme(etudiant_niveau) {
  let systeme
  if (etudiant_niveau == 'L1') {
    systeme = ['S1', 'S2']
  } else if (etudiant_niveau == 'L2') {
    systeme = ['S3', 'S4']
  } else if (etudiant_niveau == 'L3') {
    systeme = ['S5', 'S6']
  } else if (etudiant_niveau == 'M1') {
    systeme = ['S7', 'S8']
  } else if (etudiant_niveau == 'M2') {
    systeme = ['S9', 'S10']
  } else if (etudiant_niveau == 'D1') {
    systeme = ['S11', 'S12']
  } else if (etudiant_niveau == 'D2') {
    systeme = ['S13', 'S14']
  } else if (etudiant_niveau == 'D3') {
    systeme = ['S15', 'S16']
  }

  return systeme
}

async function matiereSystemReverse(semestre) {
  if (semestre == 'S1' || semestre == 'S2') {
    return 'L1'
  } else if (semestre == 'S3' || semestre == 'S4') {
    return 'L2'
  } else if (semestre == 'S5' || semestre == 'S6') {
    return 'L3'
  } else if (semestre == 'S7' || semestre == 'S8') {
    return 'M1'
  } else if (semestre == 'S9' || semestre == 'S10') {
    return 'M2'
  } else if (semestre == 'S11' || semestre == 'S12') {
    return 'D1'
  } else if (semestre == 'S13' || semestre == 'S14') {
    return 'D2'
  } else if (semestre == 'S15' || semestre == 'S16') {
    return 'D3'
  }
}

async function getNessesarytable() {
  try {
    const sql = 'SELECT * FROM nessesaryTable'
    const [rows] = await pool.query(sql)
    return rows[0]
  } catch (error) {
    return error
  }
}

async function updateNessesaryTable(id, multiplicateur) {
  const sql = 'UPDATE nessesaryTable SET uniter_heure = ? WHERE id = ?'

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

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

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

module.exports = {
  matiereSysteme,
  updateCurrentYears,
  updateStudents,
  getNessesarytable,
  updateNessesaryTable,
  matiereSystemReverse
}
