'use client'
import React, {useEffect, useLayoutEffect} from 'react'
import {config} from './config'
import {OverlayProvider} from '@gluestack-ui/core/overlay/creator'
import {ToastProvider} from '@gluestack-ui/core/toast/creator'
import {setFlushStyles} from '@gluestack-ui/utils/nativewind-utils'
import {script} from './script'

export type ModeType = 'light' | 'dark' | 'system'

const variableStyleTagId = 'nativewind-style'
const createStyle = (styleTagId: string) => {
  const style = document.createElement('style')
  style.id = styleTagId
  style.appendChild(document.createTextNode(''))
  return style
}

export const useSafeLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect

export function GluestackUIProvider({mode = 'light', ...props}: {mode?: ModeType; children?: React.ReactNode}) {
  let cssVariablesWithMode = ``
  Object.keys(config).forEach(configKey => {
    cssVariablesWithMode += configKey === 'dark' ? `\n .dark {\n ` : `\n:root {\n`
    const cssVariables = Object.keys(config[configKey as keyof typeof config]).reduce((acc: string, curr: string) => {
      acc += `${curr}:${config[configKey as keyof typeof config][curr]}; `
      return acc
    }, '')
    cssVariablesWithMode += `${cssVariables} \n}`
  })

  setFlushStyles(cssVariablesWithMode)

  const handleMediaQuery = React.useCallback((e: MediaQueryListEvent) => {
    script(e.matches ? 'dark' : 'light')
  }, [])

  useSafeLayoutEffect(() => {
    if (mode !== 'system') {
      const documentElement = document.documentElement
      if (documentElement) {
        documentElement.classList.add(mode)
        documentElement.classList.remove(mode === 'light' ? 'dark' : 'light')
        documentElement.style.colorScheme = mode
      }
    }
  }, [mode])

  useSafeLayoutEffect(() => {
    if (mode !== 'system') return
    const media = window.matchMedia('(prefers-color-scheme: dark)')

    media.addListener(handleMediaQuery)

    return () => media.removeListener(handleMediaQuery)
  }, [handleMediaQuery])

  useSafeLayoutEffect(() => {
    if (typeof window !== 'undefined') {
      const documentElement = document.documentElement
      if (documentElement) {
        const head = documentElement.querySelector('head')
        let style = head?.querySelector(`[id='${variableStyleTagId}']`)
        if (!style) {
          style = createStyle(variableStyleTagId)
          style.innerHTML = cssVariablesWithMode
          if (head) head.appendChild(style)
        }
      }
    }
  }, [])

  return (
    <>
      <script
        suppressHydrationWarning
        dangerouslySetInnerHTML={{
          __html: `(${script.toString()})('${mode}')`,
        }}
      />
      <OverlayProvider>
        <ToastProvider>{props.children}</ToastProvider>
      </OverlayProvider>
    </>
  )
}
