'use client'

import * as React from 'react'
import PropTypes from 'prop-types'
import createCache from '@emotion/cache'
import {useServerInsertedHTML} from 'next/navigation'
import {CacheProvider as DefaultCacheProvider} from '@emotion/react'

export default function NextAppDirEmotionCacheProvider(props) {
  const {options, CacheProvider = DefaultCacheProvider, children} = props

  const [registry] = React.useState(() => {
    const cache = createCache(options)
    cache.compat = true
    const prevInsert = cache.insert
    let inserted = []
    cache.insert = (...args) => {
      const [selector, serialized] = args
      if (cache.inserted[serialized.name] === undefined) {
        inserted.push({
          name: serialized.name,
          isGlobal: selector === '',
        })
      }

      return prevInsert(...args)
    }

    const flush = () => {
      const prevInserted = inserted
      inserted = []
      return prevInserted
    }

    return {cache, flush}
  })

  useServerInsertedHTML(() => {
    const inserted = registry.flush()
    if (inserted.length === 0) {
      return null
    }

    let styles = ''
    let dataEmotionAttribute = registry.cache.key

    const globals = []

    for (const {name, isGlobal} of inserted) {
      const style = registry.cache.inserted[name]

      if (typeof style !== 'boolean') {
        if (isGlobal) {
          globals.push({name, style})
        } else {
          styles += style
          dataEmotionAttribute += ` ${name}`
        }
      }
    }

    return (
      <>
        {globals.map(({name, style}) => (
          <style
            key={name}
            dangerouslySetInnerHTML={{__html: style}}
            data-emotion={`${registry.cache.key}-global ${name}`}
          />
        ))}
        {styles !== '' && (
          <style
            dangerouslySetInnerHTML={{__html: styles}}
            data-emotion={dataEmotionAttribute}
          />
        )}
      </>
    )
  })

  return <CacheProvider value={registry.cache}>{children}</CacheProvider>
}

NextAppDirEmotionCacheProvider.propTypes = {
  options: PropTypes.object.isRequired,
  CacheProvider: PropTypes.func,
  children: PropTypes.node.isRequired
}
