import { MessageCard } from 'domains/store/store.types'
import { className } from 'lib/css'
import { FunctionalComponent } from 'preact'
import { useCallback, useEffect, useMemo, useRef } from 'preact/hooks'
import { useGeneratedId, useSeamlyCommands } from 'ui/hooks/seamly-hooks'
import { actionTypes, cardTypes } from 'ui/utils/seamly-utils'

type CardComponentProps = Partial<MessageCard['payload']['body']> & {
  id?: string
  hasFocus?: boolean
  isCarouselItem?: boolean
}

const CardComponent: FunctionalComponent<CardComponentProps> = ({
  id,
  action,
  buttonText,
  description,
  hasFocus,
  image,
  title,
  isCarouselItem,
}) => {
  const cardRef = useRef<HTMLDivElement>(null)
  const { sendMessage, sendAction, emitEvent } = useSeamlyCommands()
  const descriptionId = useGeneratedId()
  const isMounted = useRef(false)

  const CardActionComponent =
    action?.type === cardTypes.navigate ? 'a' : 'button'

  const emitCardEvent = useCallback(
    () =>
      emitEvent(`action.${actionTypes.clickCard}`, {
        type: actionTypes.clickCard,
        originMessage: id,
        action,
      }),
    [emitEvent, id, action],
  )

  const handleClick = useCallback(() => {
    emitCardEvent()
    if (action?.type === cardTypes.ask) {
      sendMessage({ body: action?.ask })
    } else if (action?.type === cardTypes.topic) {
      const { topic: name, fallbackMessage } = action
      sendAction({
        type: actionTypes.setTopic,
        body: { name, fallbackMessage },
      })
    }
  }, [sendMessage, action, sendAction, emitCardEvent])

  const actionProps = useMemo(
    () =>
      action?.type === cardTypes.navigate
        ? {
            href: action?.link,
            rel: 'noopener noreferrer',
            target: action?.newTab ? '_blank' : '_self',
            onClick: emitCardEvent,
          }
        : {
            onClick: handleClick,
          },
    [action, handleClick, emitCardEvent],
  )

  useEffect(() => {
    if (isCarouselItem) {
      if (hasFocus && isMounted.current) {
        window.requestAnimationFrame(() => cardRef.current?.focus())
      } else {
        cardRef.current?.blur()
      }
    }
    isMounted.current = true
  }, [hasFocus, isCarouselItem])

  return (
    <div
      className={className('card__wrapper')}
      id={id}
      tabIndex={-1} // set tabIndex of -1 so card can be focussed
      ref={cardRef}
    >
      {image ? (
        <img className={className('card__image')} src={image} alt="" />
      ) : null}
      <div className={className('card__content')} id={id}>
        {title && <h2 className={className('card__title')}>{title}</h2>}
        {description && (
          <div
            className={className('card__description')}
            dangerouslySetInnerHTML={{ __html: description }}
          />
        )}
        <CardActionComponent
          tabIndex={isCarouselItem && !hasFocus ? -1 : undefined} // disable to prevent tabbing through cards
          className={className('button', 'button--primary')}
          aria-describedby={descriptionId}
          {...actionProps}
        >
          {buttonText}
        </CardActionComponent>
      </div>
    </div>
  )
}

export default CardComponent
