import { useStorage } from '@vueuse/core'
import { setDefaultOptions } from 'date-fns'
import { enUS, fr } from 'date-fns/locale'
import flatpickr from 'flatpickr'
import { French } from 'flatpickr/dist/l10n/fr'
import { useTheme } from 'vuetify'
import { themeConfig } from '@themeConfig'
import { cookieRef, namespaceConfig } from '@layouts/stores/config'
import { useConfigStore } from '@core/stores/config'

const _syncAppRtl = () => {
  const configStore = useConfigStore()
  const storedLang = cookieRef<string | null>('language', null)

  const { locale } = useI18n({ useScope: 'global' })

  // TODO: Handle case where i18n can't read persisted value
  if (locale.value !== storedLang.value && storedLang.value)
    locale.value = storedLang.value

  if (locale.value === 'fr') {
    if (flatpickr.l10ns.fr)
      flatpickr.localize(French)

    setDefaultOptions({ locale: fr })
  }
  else {
    if (flatpickr.l10ns.en)
      flatpickr.localize(flatpickr.l10ns.en)

    setDefaultOptions({ locale: enUS })
  }

  // watch and change lang attribute of html on language change
  watch(
    locale,
    val => {
      // Update lang attribute of html tag
      if (typeof document !== 'undefined')
        document.documentElement.setAttribute('lang', val as string)

      // Store selected language in cookie
      storedLang.value = val as string

      if (storedLang.value === 'fr') {
        if (flatpickr.l10ns.fr)
          flatpickr.localize(flatpickr.l10ns.fr)

        setDefaultOptions({ locale: fr })
      }
      else {
        if (flatpickr.l10ns.en)
          flatpickr.localize(flatpickr.l10ns.en)

        setDefaultOptions({ locale: enUS })
      }

      // set isAppRtl value based on selected language
      if (themeConfig.app.i18n.langConfig && themeConfig.app.i18n.langConfig.length) {
        themeConfig.app.i18n.langConfig.forEach(lang => {
          if (lang.i18nLang === storedLang.value)
            configStore.isAppRTL = lang.isRTL
        })
      }
    },
    { immediate: true },
  )
}

const _handleSkinChanges = () => {
  const { themes } = useTheme()
  const configStore = useConfigStore()

  // Create skin default color so that we can revert back to original (default skin) color when switch to default skin from bordered skin
  Object.values(themes.value).forEach(t => {
    t.colors['skin-default-background'] = t.colors.background
    t.colors['skin-default-surface'] = t.colors.surface
  })

  watch(
    () => configStore.skin,
    val => {
      Object.values(themes.value).forEach(t => {
        t.colors.background = t.colors[`skin-${val}-background`]
        t.colors.surface = t.colors[`skin-${val}-surface`]
      })
    },
    { immediate: true },
  )
}

/*
    ℹ️ Set current theme's surface color in localStorage

    Why? Because when initial loader is shown (before vue is ready) we need to what's the current theme's surface color.
    We will use color stored in localStorage to set the initial loader's background color.

    With this we will be able to show correct background color for the initial loader even before vue identify the current theme.
  */
const _syncInitialLoaderTheme = () => {
  const vuetifyTheme = useTheme()

  watch(
    () => useConfigStore().theme,
    () => {
      // ℹ️ We are not using theme.current.colors.surface because watcher is independent and when this watcher is ran `theme` computed is not updated
      useStorage<string | null>(namespaceConfig('initial-loader-bg'), null).value = vuetifyTheme.current.value.colors.surface
      useStorage<string | null>(namespaceConfig('initial-loader-color'), null).value = vuetifyTheme.current.value.colors.primary
    },
    { immediate: true },
  )
}

const initCore = () => {
  _syncInitialLoaderTheme()
  _handleSkinChanges()

  // ℹ️ We don't want to trigger i18n in SK
  if (themeConfig.app.i18n.enable)
    _syncAppRtl()
}

export default initCore
