import { app, shell, BrowserWindow, ipcMain, Tray, Menu } from 'electron'
import { join } from 'path'
const path = require('path')
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
import icon from '../../resources/logo.ico?asset' // Your tray icon file
const database = require('../../database/database2')

database
  .createTables()
  .then(() => database.insertDefaultAdmin())
  .then(() => database.insertStatusesIfNotExist())
  .catch(console.error)

const { createConfigIp, updateIPConfig } = require('../../database/Models/IpConfig')
const { importFileToDatabase } = require('../../database/import/Etudiants')
const { loginUser, forgotPassword, insertUser, updateUser } = require('../../database/Models/Users')
const {
  insertEtudiant,
  getSingleEtudiant,
  FilterDataByNiveau,
  updateEtudiant,
  changePDP,
  updateParcours,
  createTranche,
  getTranche,
  updateTranche,
  deleteTranche,
  deleteEtudiant,
  getSingleTranche
} = require('../../database/Models/Etudiants')
const {
  insertNiveau,
  updateNiveau,
  getSingleNiveau,
  deleteNiveau
} = require('../../database/Models/Niveau')
const {
  insertNote,
  getNote,
  updateNote,
  showMoyen,
  getMatiereAndNote,
  getNotesWithRepechToDisplay
} = require('../../database/Models/Notes')
const {
  createMatiere,
  getSingleMatiere,
  updateMatiere,
  updateMatiereNiveau,
  displayMatiereFromForm,
  deleteMatiere,
  asygnationToMention,
  getMentionMatiere,
  getMentionMatiereChecked,
  getSemestreMatiere,
  insertUpdateMentionSemestre,
  insertNewProf,
  getSIngleProf,
  updateProf
} = require('../../database/Models/Matieres')
const { importFileToDatabaseMatiere } = require('../../database/import/Matieres')
const { importNiveau } = require('../../database/import/Niveau')
const { updateSysteme } = require('../../database/Models/NoteSysrem')
const {
  createAnneeScolaire,
  deleteAnneeScolaire,
  getSingleAnneScolaire,
  updateAnneeScolaire,
  setCurrent
} = require('../../database/Models/AnneeScolaire')
const {
  createMention,
  deleteMention,
  getSingleMention,
  updateMention
} = require('../../database/Models/Mentions')
const {
  getNoteRepech,
  updateNoteRepech,
  showMoyenRepech
} = require('../../database/Models/NoteRepechage')
const {
  updateCurrentYears,
  updateStudents,
  updateNessesaryTable
} = require('../../database/function/System')
const { autoUpdater } = require('electron-updater')
const { URL } = require('../../database/api/Config')
const {
  insertParcour,
  getSingleParcours,
  deletes,
  updateparcour,
  parcourMatiere,
  deleteParcours,
  getParcourMatiere
} = require('../../database/Models/Parcours')

// Declare mainWindow and tray in the global scope
let mainWindow
let tray = null
updateCurrentYears()
updateStudents()

autoUpdater.setFeedURL({
  provider: 'generic',
  url: `${URL}/latest` // Ensure this points to the folder containing latest.yml
})

function createWindow() {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 1375,
    minWidth: 1375,
    height: 740,
    minHeight: 740,
    show: false,
    autoHideMenuBar: true,
    fullscreen: false,
    icon: path.join(__dirname, 'resources', 'logo.ico'), // Path to your icon,
    ...(process.platform === 'linux' ? { icon } : {}),
    webPreferences: {
      preload: join(__dirname, '../preload/index.js'),
      nodeIntegration: true,
      contextIsolation: true,
      sandbox: false
    }
  })

  // Désactiver les raccourcis clavier
  mainWindow.webContents.on('before-input-event', (event, input) => {
    if (input.control || input.meta || input.alt || input.key === 'F11') {
      event.preventDefault()
    }
  })

  mainWindow.on('ready-to-show', () => {
    mainWindow.maximize() // Maximiser la fenêtre
    mainWindow.show()
  })

  mainWindow.webContents.setWindowOpenHandler((details) => {
    shell.openExternal(details.url)
    return { action: 'deny' }
  })

  // Load the appropriate URL based on environment
  if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
    mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
  } else {
    mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
  }

  // Handle window close (hide instead of closing)
  mainWindow.on('close', (event) => {
    if (!app.isQuiting) {
      event.preventDefault()
      mainWindow.hide() // Minimize to tray instead of closing
    } else {
      // Destroy the tray when quitting
      if (tray) tray.destroy()
    }
  })
}

// Function to create the system tray
function createTray() {
  const iconPath = icon // Use your icon path here
  tray = new Tray(iconPath)

  // Create a context menu for the tray
  const contextMenu = Menu.buildFromTemplate([
    {
      label: 'Ouvrir',
      click: () => {
        mainWindow.show()
        mainWindow.webContents.send('navigateToRoute', '#/') // Send the route as a string
      }
    },
    {
      label: 'A Propos',
      click: () => {
        mainWindow.show()
        mainWindow.webContents.send('navigateToRoute', '#/apropos') // Send the route as a string
      }
    },
    {
      label: 'Quit',
      click: () => {
        // Clear localStorage in the renderer process
        mainWindow.webContents
          .executeJavaScript('localStorage.removeItem("ACCESS_TOKEN");')
          .then(() => {
            console.log('localStorage cleared.')
            // Ensure the app quits entirely
            if (tray) {
              app.quit()
              tray.destroy()
              // if (app.quit()) {
              //   tray.destroy()
              // }
            } // Quit the app
          })
          .catch((err) => {
            console.error('Error clearing localStorage:', err)
            // Quit the app even if clearing fails
            if (tray) {
              app.quit()
              tray.destroy()
              // if (app.quit()) {
              //   tray.destroy()
              // }
            }
          })
      }
    }
  ])

  tray.setToolTip('My Electron App')
  tray.setContextMenu(contextMenu)

  // Show the app when the tray icon is clicked
  tray.on('click', () => {
    mainWindow.show()
  })
}

app.whenReady().then(() => {
  electronApp.setAppUserModelId('com.electron')
  autoUpdater.checkForUpdatesAndNotify()

  app.on('browser-window-created', (_, window) => {
    optimizer.watchWindowShortcuts(window)
  })

  createWindow()
  createTray() // Create the tray icon

  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// When an update is available
autoUpdater.on('update-available', () => {
  dialog.showMessageBox({
    type: 'info',
    title: 'Mise à jour disponible',
    message: 'Une nouvelle version est disponible. Téléchargement en cours...'
  })
})

// When the update is downloaded
autoUpdater.on('update-downloaded', (info) => {
  dialog
    .showMessageBox({
      type: 'info',
      title: 'Mise à jour prête',
      message: `La version ${info.version} a été téléchargée. Redémarrer maintenant ?`,
      buttons: ['Redémarrer', 'Plus tard']
    })
    .then((result) => {
      if (result.response === 0) {
        autoUpdater.quitAndInstall()
      }
    })
})

// If an error occurs
autoUpdater.on('error', (error) => {
  dialog.showErrorBox('Update Error', error == null ? 'Unknown' : error.message)
})

// Quit the app when all windows are closed, except on macOS
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

// In this file you can include the rest of your app"s specific main process
// code. You can also put them in separate files and require them here.

// Event for handling login
ipcMain.handle('login', async (event, credentials) => {
  const { username, password } = credentials

  const users = await loginUser(username, password)

  if (users) {
    return { success: true, user: users }
  } else {
    return { success: false }
  }
})

// Event for handling insert other user
ipcMain.handle('insertUser', async (event, credentials) => {
  const { username, email, password, roles } = credentials

  const users = await insertUser(username, email, password, roles)

  return users
})

// event for handlign forgot password
ipcMain.handle('forgotPassword', async (event, credentials) => {
  const { email, password, passwordConfirmation } = credentials

  const updated = await forgotPassword(email, password, passwordConfirmation)

  if (updated) {
    return updated
  }
})

// event for updating users
ipcMain.handle('updateUsers', async (event, credentials) => {
  const { username, newUsername, email, newEmail, passwordVerif, password, id } = credentials

  const update = await updateUser(newUsername, newEmail, password, id)

  return update
})

// event for quit app
ipcMain.handle('quit', async () => {
  app.quit()
})

// event for minimizing the app
ipcMain.handle('minimize', async () => {
  if (mainWindow) {
    mainWindow.minimize()
  }
})

// event for insert etudiants
ipcMain.handle('insertEtudiant', async (event, credentials) => {
  const {
    nom,
    prenom,
    photos,
    date_de_naissances,
    niveau,
    annee_scolaire,
    status,
    num_inscription,
    mention_id,
    sexe,
    nationaliter,
    cin,
    date_delivrence,
    annee_bacc,
    serie,
    boursier,
    domaine,
    contact,
    parcours
  } = credentials

  const insert = await insertEtudiant(
    nom,
    prenom,
    photos,
    date_de_naissances,
    niveau,
    annee_scolaire,
    status,
    num_inscription,
    mention_id,
    sexe,
    nationaliter,
    cin,
    date_delivrence,
    annee_bacc,
    serie,
    boursier,
    domaine,
    contact,
    parcours
  )

  return insert
})

// event for fetching single
ipcMain.handle('getByNiveau', async (event, credentials) => {
  const { niveau } = credentials

  const getSingle = await FilterDataByNiveau(niveau)

  return getSingle
})

// event for fetching single
ipcMain.handle('single', async (event, credentials) => {
  const { id } = credentials

  const getSingle = await getSingleEtudiant(id)

  return getSingle
})

// event for inserting niveau
ipcMain.handle('insertNiveau', async (event, credentials) => {
  const { nom } = credentials

  const insert = await insertNiveau(nom)

  return insert
})

// event for updating etudiants
ipcMain.handle('updateETudiants', async (event, credentials) => {
  const {
    nom,
    prenom,
    photos,
    date_de_naissances,
    niveau,
    annee_scolaire,
    status,
    mention_id,
    num_inscription,
    id,
    sexe,
    nationalite,
    cin,
    date_delivrance,
    annee_bacc,
    serie,
    boursier,
    domaine,
    contact,
    parcours
  } = credentials

  const updating = await updateEtudiant(
    nom,
    prenom,
    photos,
    date_de_naissances,
    niveau,
    annee_scolaire,
    status,
    mention_id,
    num_inscription,
    id,
    sexe,
    nationalite,
    cin,
    date_delivrance,
    annee_bacc,
    serie,
    boursier,
    domaine,
    contact,
    parcours
  )

  return updating
})

// event for updating etudiants pdp
ipcMain.handle('updateETudiantsPDP', async (event, credentials) => {
  const { pdp, id } = credentials

  const updating = await changePDP(pdp, id)

  return updating
})

// event for adding notes
ipcMain.handle('insertNote', async (event, credentials) => {
  const { etudiant_id, etudiant_niveau, mention_id, formData, annee_scolaire } = credentials

  const insert = await insertNote(
    etudiant_id,
    etudiant_niveau,
    mention_id,
    formData,
    annee_scolaire
  )

  return insert
})

// event for get single note
ipcMain.handle('getSingleNote', async (event, credentials) => {
  const { id, niveau, mention_id } = credentials

  const get = await getNote(id, niveau, mention_id)

  return get
})

// event for get single note repech
ipcMain.handle('getNotesRepech', async (event, credentials) => {
  const { id, niveau, mention_id } = credentials

  const get = await getNoteRepech(id, niveau, mention_id)

  return get
})

// event for updating note
ipcMain.handle('updatetNote', async (event, credentials) => {
  const { formData, niveau, id, mention_id, annee_scolaire } = credentials

  const update = await updateNote(formData, niveau, id, mention_id, annee_scolaire)

  return update
})

// event for updating note repech
ipcMain.handle('updatetNoteRepech', async (event, credentials) => {
  const { formData2, niveau, id } = credentials

  const update = await updateNoteRepech(formData2, niveau, id)

  return update
})

// event to get single matiere
ipcMain.handle('getMatiereByID', async (event, credentials) => {
  const { id } = credentials

  const matiere = await getSingleMatiere(id)

  return matiere
})

// event for updating matiere
ipcMain.handle('updateMatiere', async (event, credentials) => {
  const { nom, credit, uniter, ue, id } = credentials

  const update = await updateMatiere(nom, id, credit, uniter, ue)

  return update
})
ipcMain.handle('updateMatiereNiveau', async (event, credentials) => {
  // credentials = { niveau_id, id }
  const update = await updateMatiereNiveau(credentials) // ✅ on passe id + niveau_id
  return update
})

// event for importExcel
ipcMain.handle('importexcel', async (event, credentials) => {
  const files = credentials
  console.log(files)
  const insert = await importFileToDatabase(files)

  return insert
})

// event for udatign a single niveau
ipcMain.handle('updateSingleNiveau', async (event, credentials) => {
  const { nom, id } = credentials

  const update = updateNiveau(nom, id)

  return update
})

// event to get single niveau
ipcMain.handle('singleNiveau', async (event, credentials) => {
  const { id } = credentials

  const update = getSingleNiveau(id)

  return update
})

// event for creating matiere
ipcMain.handle('createMatiere', async (event, credentials) => {
  const { nom, credit, uniter, ue } = credentials

  const create = createMatiere(nom, credit, uniter, ue)

  return create
})

// event for import excel matiere
ipcMain.handle('importExcelMatiere', async (event, credentials) => {
  const files = credentials
  console.log(files)
  const insert = await importFileToDatabaseMatiere(files)

  return insert
})

// event for import excel niveau
ipcMain.handle('importNiveau', async (event, credentials) => {
  const files = credentials
  console.log(files)
  const insert = await importNiveau(files)

  return insert
})

// event for updating note systeme
ipcMain.handle('updateNoteSysteme', async (event, credentials) => {
  const { id, admis, redouble, renvoyer } = credentials

  const update = updateSysteme(id, admis, redouble, renvoyer)
  return update
})

// event for updating note systeme
ipcMain.handle('createAnneeScolaire', async (event, credentials) => {
  const { code, debut, fin } = credentials

  const create = createAnneeScolaire(code, debut, fin)
  return create
})

ipcMain.handle('getMoyene', async (event, credentials) => {
  const { niveau, scolaire } = credentials
  console.log('index.js', niveau, scolaire)

  const create = showMoyen(niveau, scolaire)
  return create
})

ipcMain.handle('getMoyenneRepech', async (event, credentials) => {
  const { niveau, scolaire } = credentials
  console.log('index.js', niveau, scolaire)

  const create = showMoyenRepech(niveau, scolaire)
  return create
})

ipcMain.handle('noteMatiere', async (event, credentials) => {
  const { id, niveau, annee_scolaire } = credentials

  const get = getMatiereAndNote(id, niveau, annee_scolaire)
  return get
})

ipcMain.handle('displayMatiereFromForm', async (event, credentials) => {
  const { niveau, mention_id, parcours } = credentials

  const get = displayMatiereFromForm(niveau, mention_id, parcours)
  return get
})

ipcMain.handle('createMention', async (event, credentials) => {
  const { nom, uniter } = credentials

  const get = createMention(nom, uniter)
  return get
})

ipcMain.handle('getSingleMention', async (event, credentials) => {
  const { id } = credentials

  const get = getSingleMention(id)
  return get
})

ipcMain.handle('updateMention', async (event, credentials) => {
  const { nom, uniter, id } = credentials

  const get = updateMention(nom, uniter, id)
  return get
})

ipcMain.handle('deleteMention', async (event, credentials) => {
  const { id } = credentials

  const get = deleteMention(id)
  return get
})

ipcMain.handle('deleteNiveaus', async (event, credentials) => {
  const { id } = credentials

  const get = deleteNiveau(id)
  return get
})

ipcMain.handle('deleteMatiere', async (event, id) => {
  return await deleteMatiere(id);
});


ipcMain.handle('asign', async (event, credentials) => {
  const { formData, id } = credentials
  // console.log(formData, id);
  const get = asygnationToMention(formData, id)

  return get
})

ipcMain.handle('asignSemestre', async (event, credentials) => {
  const { id } = credentials

  const get = getMentionMatiereChecked(id)

  return get
})

ipcMain.handle('getAsign', async (event, credentials) => {
  const { id } = credentials
  // console.log(formData, id);
  const get = getMentionMatiere(id)

  return get
})

ipcMain.handle('deleteAnneeScolaire', async (event, credentials) => {
  const { id } = credentials
  // console.log(formData, id);
  const get = deleteAnneeScolaire(id)

  return get
})

ipcMain.handle('getSemestreMatiere', async (event, credentials) => {
  const { id } = credentials
  // console.log(formData, id);
  const get = getSemestreMatiere(id)

  return get
})

ipcMain.handle('insertUpdateMentionSemestre', async (event, credentials) => {
  const { id, selectedSemestres } = credentials
  // console.log(formData, id);
  const get = insertUpdateMentionSemestre(id, selectedSemestres)

  return get
})

ipcMain.handle('getSingleAnneeScolaire', async (event, credentials) => {
  const { id } = credentials
  // console.log(formData, id);
  const get = getSingleAnneScolaire(id)

  return get
})

ipcMain.handle('updateAnneeScolaire', async (event, credentials) => {
  const { code, debut, fin, id } = credentials
  // console.log(formData, id);
  const get = updateAnneeScolaire(id, code, debut, fin)

  return get
})

ipcMain.handle('setCurrent', async (event, credentials) => {
  const { id } = credentials
  // console.log(formData, id);
  const get = setCurrent(id)

  return get
})

ipcMain.handle('noteRelerer', async (event, credentials) => {
  const { id, anneescolaire, niveau } = credentials
  // console.log(formData, id);
  const get = getNotesWithRepechToDisplay(id, anneescolaire, niveau)

  return get
})

ipcMain.handle('updateNessesary', async (event, credentials) => {
  const { id, multiplicateur } = credentials
  // console.log(formData, id);
  const get = updateNessesaryTable(id, multiplicateur)

  return get
})

ipcMain.handle('insertProf', async (event, credentials) => {
  const { nom_enseignant, prenom_enseignant, contact, date, matiere_id } = credentials
  // console.log(formData, id);
  const get = insertNewProf(matiere_id, nom_enseignant, prenom_enseignant, contact, date)

  return get
})

ipcMain.handle('insertParcours', async (event, credentials) => {
  const { nom, uniter, mention_id } = credentials
  // console.log(formData, id);
  const get = insertParcour(nom, uniter, mention_id)

  return get
})

ipcMain.handle('getSingleParcours', async (event, credentials) => {
  const { id } = credentials
  // console.log(formData, id);
  const get = getSingleParcours(id)

  return get
})

  ipcMain.handle('deleteParcours', async (event, id) => {
    return await deleteParcours(id);
  });

ipcMain.handle('updateParcours', async (event, credentials) => {
  const { nom, uniter, mention_id, id } = credentials
  // console.log(formData, id);
  const get = updateparcour(id, nom, uniter, mention_id)

  return get
})

ipcMain.handle('parcourMatiere', async (event, credentials) => {
  const { matiere_id, parcour_id } = credentials
  // console.log(formData, id);
  const get = parcourMatiere(matiere_id, parcour_id)

  return get
})

ipcMain.handle('getSingleProf', async (event, credentials) => {
  const { id } = credentials
  // console.log(formData, id);
  const get = getSIngleProf(id)

  return get
})

ipcMain.handle('updateProf', async (event, credentials) => {
  const { nom_enseignant, prenom_enseignant, contact, date, matiere_id } = credentials
  // console.log(formData, id);
  const get = updateProf(matiere_id, nom_enseignant, prenom_enseignant, contact, date)

  return get
})

ipcMain.handle('extractFiches', async (event, credentials) => {
  const { matiere_id } = credentials
  // console.log(formData, id);
  const get = extractFiche(matiere_id)

  return get
})

ipcMain.handle('getParcourMatiere', async (event, credentials) => {
  const { matiere_id } = credentials
  // console.log(formData, id);
  const get = getParcourMatiere(matiere_id)

  return get
})

ipcMain.handle('changeParcours', async (event, credentials) => {
  const { parcours, user_id } = credentials
  // console.log(formData, id);
  const get = updateParcours(parcours, user_id)

  return get
})

ipcMain.handle('createTranche', async (event, credentials) => {
  const { etudiant_id, tranchename, montant } = credentials
  // console.log(formData, id);
  const get = createTranche(etudiant_id, tranchename, montant)

  return get
})

ipcMain.handle('getTranche', async (event, credentials) => {
  const { id } = credentials
  // console.log(formData, id);
  const get = getTranche(id)

  return get
})

ipcMain.handle('updateTranche', async (event, credentials) => {
  const { id, tranchename, montant } = credentials
  // console.log(formData, id);
  const get = updateTranche(id, tranchename, montant)

  return get
})

ipcMain.handle('deleteTranche', async (event, credentials) => {
  const { id } = credentials
  console.log(id)
  const get = deleteTranche(id)

  return get
})

ipcMain.handle('deleteEtudiant', async (event, id) => {
  return await deleteEtudiant(id);
});

ipcMain.handle('getSingleTranche', async (event, credentials) => {
  const { id } = credentials
  // console.log(formData, id);
  const get = getSingleTranche(id)

  return get
})

ipcMain.handle('createIPConfig', async (event, credentials) => {
  const { ipname } = credentials
  // console.log(formData, id);
  const get = createConfigIp(ipname)

  return get
})

ipcMain.handle('updateIPConfig', async (event, credentials) => {
  const { id, ipname } = credentials
  // console.log(formData, id);
  const get = updateIPConfig(id, ipname)

  return get
})
