import classNames from 'classnames'
import React, { ChangeEvent, useState } from 'react'
import { Popover } from 'react-tiny-popover'
import { useZocksStore } from '../../../app'
import { selectIsConnecting } from '../../../store'
import { ErrorResponse, getClassName, getMergedClassNames } from '../../common'
import { JoinPageRoomInputProps, RoomJoinSelectOption } from './models'
import zocksStyle from './JoinPageRoomInput.module.scss'

export const JoinPageRoomInput: React.FC<JoinPageRoomInputProps> = ({
  initialRoomJoinInputValue = '',
  initialRoomJoinSelectValue = 'id',
  joinAction,
  baseJoinOptions,
  roomIdInputLabel = 'Enter a Meeting ID',
  roomIdInputDisabled,
  roomIdPlaceholder = 'Meeting ID',
  joinButtonLabel = 'Join the Meeting',
  hideInputSelect = false,
  styles,
}) => {
  const isConnecting = useZocksStore(selectIsConnecting)

  const [roomJoinInput, setRoomJoinInput] = useState<string>(initialRoomJoinInputValue)
  const [roomJoinInputSelectValue, setRoomJoinInputSelectValue] =
    useState<RoomJoinSelectOption>(initialRoomJoinSelectValue)

  const [isPopoverOpen, setPopoverOpen] = useState<boolean>(false)
  const [hasError, setHasError] = useState<boolean>(false)
  const [error, setError] = useState<string>('')

  const mergedStyles = getMergedClassNames(zocksStyle, styles)

  const joinErrorTooltip = () => (
    <div className={getClassName('join_page__room-input-popover', mergedStyles)}>
      <div className={getClassName('join-page__room-input-popover-text', mergedStyles)}>{error}</div>
    </div>
  )

  const joinErrorCallback = (e: ErrorResponse | string) => {
    setError(typeof e === 'string' ? e : e.errors.map((v) => v.message).join(', '))
    setPopoverOpen(true)
    setHasError(true)
  }

  const joinOptions = {
    roomId: roomJoinInputSelectValue === 'id' ? roomJoinInput : '',
    roomName: roomJoinInputSelectValue === 'name' ? roomJoinInput : '',
    joinErrorCallback,
    ...baseJoinOptions,
  }

  const onRoomJoinInputChange = (evt: ChangeEvent<HTMLInputElement>) => {
    setHasError(false)
    setPopoverOpen(false)
    setRoomJoinInput(evt.target.value)
  }

  const onRoomJoinInputKeyUp = (evt: React.KeyboardEvent<HTMLInputElement>) => {
    if (roomJoinInput && evt.key === 'Enter') {
      joinAction(joinOptions)
    }
  }

  const onRoomJoinSelectChange = (evt: ChangeEvent<HTMLSelectElement>) => {
    setRoomJoinInputSelectValue(evt.target.value as RoomJoinSelectOption)
  }

  return (
    <div className={getClassName('join-page__join-room-container', mergedStyles)}>
      <Popover isOpen={isPopoverOpen} content={() => joinErrorTooltip()} positions={['top']}>
        <div className={getClassName('join-page__room-input-wrapper', mergedStyles)}>
          <input
            onMouseEnter={() => setPopoverOpen(hasError)}
            onMouseLeave={() => setPopoverOpen(false)}
            className={classNames(getClassName('join-page__room-input', mergedStyles), {
              [getClassName('join-page__room-input--error', mergedStyles)]: hasError,
            })}
            type='text'
            onChange={onRoomJoinInputChange}
            onKeyUp={onRoomJoinInputKeyUp}
            value={roomJoinInput}
            placeholder={roomIdPlaceholder}
            aria-label={roomIdInputLabel}
            disabled={roomIdInputDisabled}
          />
          {!hideInputSelect && (
            <select
              onChange={onRoomJoinSelectChange}
              className={getClassName('join-page__room-input-select', mergedStyles)}
              value={roomJoinInputSelectValue}
            >
              <option value='name'>Name</option>
              <option value='id'>Id</option>
            </select>
          )}
        </div>
      </Popover>
      <button
        className={getClassName('join-page__join-button', mergedStyles)}
        onClick={() => joinAction(joinOptions)}
        disabled={!roomJoinInput || isConnecting || hasError}
      >
        {joinButtonLabel}
      </button>
    </div>
  )
}
