let darkModeNodeParent = import.meta.client ? document.body : null

/**
 * Handle form public pages dark mode and transparent mode
 */
export function handleDarkMode (darkMode, elem = null) {
  if (import.meta.server)
    return

  darkModeNodeParent = elem ?? document.body

  // Dark mode
  if (['dark', 'light'].includes(darkMode))
    return handleDarkModeToggle(darkMode === 'dark')

  // Case auto
  handleDarkModeToggle(
    window.matchMedia('(prefers-color-scheme: dark)').matches
  )

  // Create listener
  window
    .matchMedia('(prefers-color-scheme: dark)')
    .addEventListener('change', handleDarkModeToggle)
}

export function useClassWatcher (elem, className) {
  const hasClass = ref(false)

  const updateClassPresence = () => {
    hasClass.value = elem.value?.classList.contains(className) ?? false
  }

  let observer = null

  const startObserving = () => {
    if (elem.value) {
      updateClassPresence()
      observer = new MutationObserver(updateClassPresence)
      observer.observe(elem.value, { attributes: true, attributeFilter: ['class'] })
    }
  }

  const stopObserving = () => {
    if (observer) {
      observer.disconnect()
      observer = null
    }
  }

  onMounted(() => {
    watch(elem, (newElem, oldElem, onCleanup) => {
      stopObserving()
      startObserving()
      onCleanup(stopObserving)
    }, { immediate: true })
  })

  onUnmounted(() => {
    stopObserving()
  })

  return computed(() => hasClass.value)
}

export function useDarkMode (elem = ref(null)) {
  // Define a computed property to handle the element reference reactively
  const effectiveElem = computed(() => {
    return elem.value || (process.client ? document.body : null)
  })

  // Pass the computed property to useClassWatcher
  return useClassWatcher(effectiveElem, 'dark')
}

export function darkModeEnabled (elem = ref(null)) {
  if (import.meta.server)
    return ref(false)

  // TODO: replace this with a function that returns a watcher for the given of dark class element
  // Simplify this
  const isDark = ref(false)

  // Update isDark based on the current class
  const updateIsDark = () => {
    const finalElement = elem.value ?? document.body
    isDark.value = finalElement.classList.contains('dark')
  }

  // MutationObserver callback to react to class changes
  let observer = new MutationObserver(updateIsDark)

  // Initialize and clean up the observer
  const initObserver = (element) => {
    if (observer) {
      observer.disconnect()
    }
    if (element) {
      observer = new MutationObserver(updateIsDark)
      observer.observe(element, { attributes: true, attributeFilter: ['class'] })
    }
  }

  onMounted(() => {
    if (!import.meta.server) {
      initObserver(elem)
    }
  })

  onUnmounted(() => {
    if (observer) {
      observer.disconnect()
    }
  })

  // Return a computed ref that depends on isDark
  return computed(() => isDark.value)
}

function handleDarkModeToggle (enabled) {
  if (enabled !== false && enabled !== true) {
    // if we received an event
    enabled = enabled.matches
  }
  enabled
    ? darkModeNodeParent.classList.add('dark')
    : darkModeNodeParent.classList.remove('dark')
}

export function disableDarkMode () {
  if (import.meta.server)
    return
  const body = document.body
  body.classList.remove('dark')
  // Remove event listener
  window
    .matchMedia('(prefers-color-scheme: dark)')
    .removeEventListener('change', handleDarkModeToggle)
}

export function handleTransparentMode (transparentModeEnabled) {
  if (import.meta.server)
    return
  if (!useIsIframe() || !transparentModeEnabled)
    return

  const app = document.getElementById('app')
  app.classList.remove('bg-white')
  app.classList.remove('dark:bg-notion-dark')
  app.classList.add('bg-transparent')
}

export function focusOnFirstFormElement () {
  if (import.meta.server)
    return
  for (const ele of document.querySelectorAll(
    'input,button,textarea,[role="button"]'
  )) {
    if (ele.offsetWidth !== 0 || ele.offsetHeight !== 0) {
      ele.focus()
      break
    }
  }
}
