import classNames from 'classnames'
import React, { ChangeEvent, useState } from 'react'
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'
import { JoinPageErrorComponent } from './JoinPageErrorComponent'

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,
  components,
}) => {
  const isConnecting = useZocksStore(selectIsConnecting)

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

  const [errorMessage, setErrorMessage] = useState<string | null>(null)
  const [hasError, setHasError] = useState<boolean>(false)

  const mergedStyles = getMergedClassNames(zocksStyle, styles)

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

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

  const onRoomJoinInputChange = (evt: ChangeEvent<HTMLInputElement>) => {
    setHasError(false)
    setErrorMessage(null)
    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)
  }

  const JoinPageRoomInputErrorElement = components?.ErrorComponent ?? JoinPageErrorComponent

  return (
    <div className={getClassName('join-page__join-room-container', mergedStyles)}>
      {errorMessage && <JoinPageRoomInputErrorElement message={errorMessage} />}
      <div className={getClassName('join-page__room-input-wrapper', mergedStyles)}>
        <input
          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>
      <button
        className={getClassName('join-page__join-button', mergedStyles)}
        onClick={() => joinAction(joinOptions)}
        disabled={!roomJoinInput || isConnecting || hasError}
      >
        {joinButtonLabel}
      </button>
    </div>
  )
}
