import { useUserHasResponded } from 'domains/app/hooks'
import { useConfig } from 'domains/config/hooks'
import { useI18n } from 'domains/i18n/hooks'
import { useVisibility } from 'domains/visibility/hooks'
import { createFocusTrap, FocusTrap } from 'focus-trap'
import { className } from 'lib/css'
import { ComponentChildren } from 'preact'
import { forwardRef, useEffect, useRef } from 'preact/compat'
import Suggestions from 'ui/components/suggestions'
import { useSeamlyAppContainerClassNames } from 'ui/hooks/component-helper-hooks'
import { useWindowOpenButtonFocusing } from 'ui/hooks/focus-helper-hooks'
import { useSeamlyLayoutMode } from 'ui/hooks/seamly-state-hooks'
import { useGeneratedId } from 'ui/hooks/utility-hooks'

const Chat = forwardRef<
  HTMLElement,
  { children: ComponentChildren; className?: string }
>(({ children, className: givenClassName = '' }, forwardedRef) => {
  const focusTrap = useRef<FocusTrap>(null)
  const { closeChat, isOpen, isVisible } = useVisibility()
  const focusWindowOpenButton = useWindowOpenButtonFocusing()
  const { namespace, layoutMode } = useConfig()
  const { isInline } = useSeamlyLayoutMode()
  const appContainerClassNames = useSeamlyAppContainerClassNames()
  const chatSectionId = useGeneratedId()
  const headingId = useGeneratedId()
  const userHasResponded = useUserHasResponded()
  const { t } = useI18n()

  const defaultClassNames = [
    'chat',
    `chat--layout-${layoutMode}`,
    `namespace--${namespace}`,
  ]

  const classNames = [...defaultClassNames, givenClassName]

  if (typeof appContainerClassNames !== 'function') {
    classNames.push(...appContainerClassNames)
  }

  if (!isOpen && layoutMode !== 'app') {
    classNames.push('chat--collapsed')
  }

  if (userHasResponded) {
    classNames.push('chat--user-responded')
  }

  const onKeyDownHandler = (e) => {
    if ((e.code && e.code === 'Escape') || e.keyCode === 27)
      if (!isInline && isOpen) {
        closeChat()
        focusWindowOpenButton()
      }
  }

  useEffect(() => {
    if (isVisible && layoutMode === 'window') {
      focusTrap.current = createFocusTrap(`#${chatSectionId}`, {
        // We set the initialFocus to false, as the `WindowOpenButton` takes care of that
        initialFocus: false,
        // Allow outside clicks to deactive the focus trap, so users can still navigate and use the site they are on
        // Users for which the focus trap is intended will (usually) not trigger this, and if they do, also intend this to happen
        clickOutsideDeactivates: true,
      })
      focusTrap.current.activate()
    }

    return () => {
      if (focusTrap.current) {
        focusTrap.current.deactivate()
      }
    }
  }, [chatSectionId, isVisible, layoutMode])

  return (
    isVisible && (
      <section
        id={chatSectionId}
        className={className(classNames)}
        onKeyDown={onKeyDownHandler}
        tabIndex={-1}
        ref={forwardedRef}
        role={layoutMode === 'window' ? 'dialog' : undefined}
        aria-labelledby={headingId}
      >
        <h2
          className={className('chat__title', 'visually-hidden')}
          id={headingId}
        >
          {t('window.srModalLayoutLabel')}
        </h2>
        <div className={className('chat-wrapper')}>{children}</div>
        {layoutMode === 'inline' && isOpen && <Suggestions isAside={true} />}
      </section>
    )
  )
})

export default Chat
