'use client'

import { ChangeEvent, createElement, forwardRef, HTMLProps, ReactNode } from 'react'

import { PktButton } from '../button/Button'

interface SearchSuggestion {
  title?: string
  text?: string
  href?: string
  onClick?: () => void
}

interface ISearch extends HTMLProps<HTMLInputElement> {
  appearance?: 'local' | 'local-with-button' | 'global'
  disabled?: boolean
  fullwidth?: boolean
  id: string
  label?: string
  name?: string
  placeholder?: string
  suggestions?: SearchSuggestion[]
  value?: string | undefined
  onSearch?: (value: string) => void
  onSuggestionClick?: (index: number) => void
  action?: string
  method?: 'get' | 'post' | 'dialog'
}

interface ISearchForm extends ISearch {
  action?: string
  method?: 'get' | 'post' | 'dialog'
}

interface ISearchInput extends ISearch {
  onChange: (event: ChangeEvent<HTMLInputElement>) => void
  disabled?: boolean
}

export const PktSearchInput = forwardRef<HTMLInputElement, ISearchInput | ISearchForm>(
  (
    {
      appearance = 'local',
      disabled = false,
      fullwidth = false,
      id,
      label,
      name,
      placeholder = 'Søk…',
      suggestions,
      value = '',
      action,
      method,
      onChange,
      onSearch,
      onSuggestionClick,
      ...props
    },
    ref,
  ) => {
    const handleSuggestionClick = (cb: (() => void) | undefined, index: number) => {
      if (cb) {
        cb()
      } else if (onSuggestionClick) {
        onSuggestionClick(index)
      }
    }

    const handleNoOnChange = (e: ChangeEvent<HTMLInputElement>) => {
      value = e.target.value
    }

    const wrapperClass = `pkt-searchinput pkt-searchinput--${appearance} ${
      fullwidth ? 'pkt-searchinput--fullwidth' : ''
    }`

    let WrapperElement
    if (action) {
      // eslint-disable-next-line react/display-name
      WrapperElement = (children: ReactNode) => (
        <form role="search" className={wrapperClass} action={action} method={method}>
          {children}
        </form>
      )
    } else {
      // eslint-disable-next-line react/display-name
      WrapperElement = (children: ReactNode) => (
        <div role="search" className={wrapperClass}>
          {children}
        </div>
      )
    }

    return WrapperElement(
      <>
        {label && (
          <label htmlFor={label ? id : undefined} className={label ? 'pkt-inputwrapper__label' : ''}>
            {label}
          </label>
        )}
        <div className={appearance === 'local' ? 'pkt-input__container' : 'pkt-searchinput__field'}>
          <input
            className={`pkt-input ${fullwidth ? 'pkt-input--fullwidth' : ''}`}
            type="search"
            name={name || id}
            id={id}
            placeholder={placeholder}
            defaultValue={value}
            disabled={disabled}
            autoComplete="off"
            aria-autocomplete="list"
            ref={ref}
            aria-controls={`${id}-suggestions`}
            onChange={onChange ? onChange : handleNoOnChange}
            onKeyUp={
              onSearch &&
              ((event) => {
                if (event.key === 'Enter') {
                  event.preventDefault()
                  onSearch(value)
                }
              })
            }
            {...props}
          />
          <PktButton
            className={`pkt-searchinput__button ${appearance === 'local' ? 'pkt-input-icon' : ''}`}
            variant="icon-only"
            iconName="magnifying-glass-big"
            skin={appearance === 'local' ? 'tertiary' : 'primary'}
            color={appearance === 'global' ? 'yellow' : undefined}
            type="submit"
            disabled={disabled}
            onClick={
              onSearch &&
              ((event) => {
                event.preventDefault()
                onSearch(value)
              })
            }
          >
            {label || placeholder}
          </PktButton>
        </div>

        {suggestions && (
          <ul id={`${id}-suggestions`} className="pkt-searchinput__suggestions" aria-live="assertive">
            {suggestions.map((suggestion, index) => (
              <li key={`search-suggestion-${index}`}>
                {createElement(
                  suggestion.href ? 'a' : suggestion.onClick ? 'button' : 'div',
                  {
                    href: suggestion.href,
                    className: `pkt-searchinput__suggestion ${suggestion.onClick ? 'pkt-link-button' : ''} ${
                      suggestion.href || suggestion.onClick ? 'pkt-searchinput__suggestion--has-hover' : ''
                    }`,
                    type: suggestion.onClick ? 'button' : undefined,
                    onClick: () => handleSuggestionClick(suggestion.onClick, index),
                    onKeyUp: (event: { key: string }) =>
                      event.key === 'Enter' && handleSuggestionClick(suggestion.onClick, index),
                  },
                  <>
                    {suggestion.title && <h3 className="pkt-searchinput__suggestion-title">{suggestion.title}</h3>}
                    {suggestion.text && <p className="pkt-searchinput__suggestion-text">{suggestion.text}</p>}
                  </>,
                )}
              </li>
            ))}
          </ul>
        )}
      </>,
    )
  },
)

PktSearchInput.displayName = 'PktSearchInput'
