import './styles/styles.css'
import { createApp, ref } from 'vue'

import { App } from './app'

import router from './router'
import { CaminoConfig } from 'camino-common/src/static/config'
import { newGetWithJson } from './api/client-rest'
import { initMatomo } from './stats/matomo'
import type { User } from 'camino-common/src/roles'
import { userKey, entreprisesKey } from './moi'
import type { Entreprise } from 'camino-common/src/entreprise'
import { isNotNullNorUndefined } from 'camino-common/src/typescript-tools'
import { CaminoError } from 'camino-common/src/zod-tools'
// Le Timeout du sse côté backend est mis à 30 secondes, toujours avoir une valeur plus haute ici
const sseTimeoutInSeconds = 45

let caminoApplicationVersion = localStorage.getItem('caminoApplicationVersion')
let lastMessageReceivedFromServer = new Date()

let eventSource: EventSource | null = null

const newEventSource = () => {
  eventSource = new EventSource('/stream/version')
  lastMessageReceivedFromServer = new Date()
  eventSource.addEventListener('version', event => {
    lastMessageReceivedFromServer = new Date()
    if (caminoApplicationVersion === null || caminoApplicationVersion === undefined) {
      localStorage.setItem('caminoApplicationVersion', event.data)
      caminoApplicationVersion = event.data
    } else if (event.data !== caminoApplicationVersion) {
      localStorage.setItem('caminoApplicationVersion', event.data)
      caminoApplicationVersion = event.data
      eventSource?.close()
      eventSource = null
      window.location.reload()
    }
  })
}

const checkEventSource = () => {
  setTimeout(function () {
    if (eventSource === null) {
      newEventSource()
    } else {
      if (Math.abs(lastMessageReceivedFromServer.getTime() - new Date().getTime()) / 1000 > sseTimeoutInSeconds) {
        console.warn('le serveur est injoignable, tentative de reconnexion')
        eventSource?.close()
        eventSource = null
      }
    }

    checkEventSource()
  }, 30_000)
}

checkEventSource()
Promise.resolve().then(async (): Promise<void> => {
  const [configFromJson, user, entreprises]: [CaminoConfig | CaminoError<string>, User | CaminoError<string>, Entreprise[] | CaminoError<string>] = await Promise.all([
    newGetWithJson('/config', {}),
    newGetWithJson('/moi', {}),
    newGetWithJson('/rest/entreprises', {}),
  ])
  const app = createApp(App)
  // TODO 2024-09-24 mieux gérer les cas d'erreurs
  if (isNotNullNorUndefined(user) && 'message' in user) {
    console.error(user.message)
    throw new Error("Une erreur s'est produite lors de la récupération de l'utilisateur")
  }
  if (isNotNullNorUndefined(entreprises) && 'message' in entreprises) {
    console.error(entreprises.message)
    throw new Error("Une erreur s'est produite lors de la récupération des entreprises")
  }
  app.provide(userKey, user)
  app.provide(entreprisesKey, ref(entreprises))
  // TODO 2024-09-17 mieux gérer ce cas d'erreur
  if (!('message' in configFromJson) && isNotNullNorUndefined(configFromJson.CAMINO_STAGE)) {
    try {
      if (!configFromJson.API_MATOMO_URL || !configFromJson.API_MATOMO_ID || !configFromJson.CAMINO_STAGE) throw new Error('host et/ou siteId manquant(s)')

      await initMatomo({
        host: configFromJson.API_MATOMO_URL,
        siteId: configFromJson.API_MATOMO_ID,
        environnement: configFromJson.CAMINO_STAGE,
        router,
      })
    } catch (e) {
      console.error('erreur : matomo :', e)
    }
  }
  app.use(router)
  app.mount('app-root')
})
