import { useI18n } from 'domains/i18n/hooks'
import type { MessageChoicePrompt } from 'domains/store/store.types'
import { useTranslatedEventData } from 'domains/translations/hooks'
import { className } from 'lib/css'
import { randomId } from 'lib/id'
import { toChildArray } from 'preact'
import { FC } from 'preact/compat'
import { useEffect, useMemo, useState } from 'preact/hooks'
import MessageContainer from 'ui/components/conversation/message-container'
import Icon from 'ui/components/layout/icon'
import { useSeamlyHasConversation } from 'ui/hooks/seamly-api-hooks'
import {
  useGeneratedId,
  useLastMessageEventId,
  useSeamlyCommands,
  useSeamlyServiceInfo,
} from 'ui/hooks/seamly-hooks'
import { childIsVNode } from 'ui/utils/general-utils'
import { actionTypes } from 'ui/utils/seamly-utils'

export const useChoicePrompt = (event: MessageChoicePrompt) => {
  const { payload } = event
  const [showOptions, setShowOptions] = useState(false)
  const { addMessageBubble, emitEvent, sendAction } = useSeamlyCommands()
  const hasConversation = useSeamlyHasConversation()
  const { activeServiceSessionId } = useSeamlyServiceInfo()
  const lastEventId = useLastMessageEventId()
  const { body } = useTranslatedEventData(event)
  const { service } = payload

  const subEvent = useMemo(() => {
    if (event.payload.type !== 'choice_prompt') return undefined

    return {
      ...event,
      payload: {
        ...event.payload,
        body: event.payload.body?.prompt,
        translatedBody: event.payload.translatedBody && {
          ...event.payload.translatedBody,
          data: event.payload.translatedBody?.prompt,
        },
      },
    }
  }, [event])

  const chooseAgain =
    body?.chooseAgain &&
    activeServiceSessionId === service?.serviceSessionId &&
    payload.id !== lastEventId

  useEffect(() => {
    setShowOptions(payload.id === lastEventId)
  }, [payload, lastEventId])

  const onChoiceClickHandler = (choice) => {
    // Do not allow interaction without a conversation
    if (!hasConversation()) {
      return
    }

    const transactionId = randomId()
    const action = {
      type: actionTypes.pickChoice,
      originMessage: payload.id,
      choice: {
        chooseAgain,
        id: choice.id,
      },
      transactionId,
    }

    addMessageBubble(choice.text, transactionId)
    sendAction(action)
    setShowOptions(false)
    emitEvent(`action.${action.type}`, {
      ...action,
      choice: { ...action.choice, text: choice.text },
    })
  }

  const onChooseAgainClickHandler = () => {
    setShowOptions((s) => !s)
  }

  return {
    body,
    subEvent,
    showOptions,
    chooseAgain,
    onChoiceClickHandler,
    onChooseAgainClickHandler,
  }
}

type ChoicePromptProps = {
  event: MessageChoicePrompt
}

const ChoicePrompt: FC<ChoicePromptProps> = ({ event, children, ...props }) => {
  const { t } = useI18n()
  const descriptorId = useGeneratedId()

  const {
    body,
    subEvent,
    showOptions,
    chooseAgain,
    onChoiceClickHandler,
    onChooseAgainClickHandler,
  } = useChoicePrompt(event)

  return (
    <>
      {toChildArray(children)
        .filter(childIsVNode)
        .map((child) => {
          child.props = {
            ...child.props,
            event: subEvent,
            id: descriptorId,
            showTranslationToggle: false,
          }
          return child
        })}
      {chooseAgain && (
        <button
          type="button"
          className={className(
            'button',
            'button--secondary',
            'button--choose-again',
          )}
          aria-expanded={showOptions ? 'true' : 'false'}
          onClick={onChooseAgainClickHandler}
          aria-describedby={descriptorId}
        >
          {showOptions
            ? t('message.choicePrompts.cancelChooseAgain')
            : t('message.choicePrompts.chooseAgain')}
          <Icon name="chevronDown" size="8" alt="" />
        </button>
      )}
      {showOptions && (
        <MessageContainer
          type="choice-prompt"
          showParticipant={false}
          event={event}
          {...props}
        >
          <ul className={className('choice-prompt', 'choice-prompt--many')}>
            {body?.choices?.map((choice) => (
              <li
                key={choice.id}
                className={className('choice-prompt__item', {
                  [`choice-prompt__item--${choice?.category}`]:
                    !!choice.category,
                })}
              >
                <button
                  type="button"
                  className={className('button', 'button--primary')}
                  onClick={() => {
                    onChoiceClickHandler(choice)
                  }}
                >
                  {choice.text}
                </button>
              </li>
            ))}
          </ul>
        </MessageContainer>
      )}
    </>
  )
}

export default ChoicePrompt
