'use client'

import { ForwardedRef, forwardRef, type ReactNode, RefAttributes } from 'react'

import { useFocusModality } from '../../hooks/useFocusModality'
import { PktAlert } from '../alert/Alert'
import { PktHelptext } from '../helptext/Helptext'

export interface IPktInputWrapper extends RefAttributes<HTMLElement> {
  forId: string
  label: string
  helptext?: string | ReactNode
  helptextDropdown?: string | ReactNode
  helptextDropdownButton?: string
  counter?: boolean
  counterCurrent?: number
  counterMaxLength?: number
  optionalTag?: boolean
  optionalText?: string
  requiredTag?: boolean
  requiredText?: string
  tagText?: string | null
  hasError?: boolean
  errorMessage?: string | ReactNode
  disabled?: boolean
  inline?: boolean
  ariaDescribedby?: string
  useWrapper?: boolean
  children?: ReactNode
  className?: string
  hasFieldset?: boolean
  role?: string
  counterPosition?: 'top' | 'bottom'
  size?: 'small' | 'medium' | 'xsmall'
}

export const PktInputWrapper = forwardRef(
  (
    {
      forId,
      label,
      helptext,
      helptextDropdown,
      helptextDropdownButton,
      counter,
      counterCurrent = 0,
      counterMaxLength,
      optionalTag = false,
      optionalText = 'Valgfritt',
      requiredTag = false,
      requiredText = 'Må fylles ut',
      tagText = null,
      hasError = false,
      errorMessage,
      disabled = false,
      inline = false,
      ariaDescribedby,
      useWrapper = true,
      children,
      className = '',
      hasFieldset = false,
      role = 'group',
      counterPosition = 'bottom',
      size = 'medium',
    }: IPktInputWrapper,
    ref: ForwardedRef<HTMLDivElement>,
  ) => {
    const focusModality = useFocusModality<HTMLDivElement>(ref)

    const describedBy = ariaDescribedby || (helptext ? `${forId}-helptext` : undefined)
    const showCounter = !!counter
    const counterTop = showCounter && counterPosition === 'top'
    const counterBottom = showCounter && counterPosition === 'bottom'

    const wrapperClasses = [
      'pkt-inputwrapper',
      className,
      hasError ? 'pkt-inputwrapper--error' : '',
      disabled ? 'pkt-inputwrapper--disabled' : '',
      inline ? 'pkt-inputwrapper--inline' : '',
      size ? `pkt-inputwrapper--${size}` : '',
    ]
      .filter(Boolean)
      .join(' ')

    const tagClasses = ['pkt-tag', 'pkt-tag--small', 'pkt-tag--thin-text'].join(' ')

    const Counter = () =>
      showCounter ? (
        <div className="pkt-input__counter" aria-live="polite" aria-atomic="true">
          {counterCurrent}
          {counterMaxLength ? `/${counterMaxLength}` : ''}
        </div>
      ) : null

    const renderTags = () => {
      return (
        <>
          {tagText && <span className={tagClasses + ` pkt-tag--gray`}>{tagText}</span>}
          {optionalTag && <span className={tagClasses + ` pkt-tag--blue-light`}>{optionalText}</span>}
          {requiredTag && <span className={tagClasses + ` pkt-tag--beige`}>{requiredText}</span>}
        </>
      )
    }
    const renderLabel = () => {
      const labelContent = (
        <>
          {label} {renderTags()}
        </>
      )

      if (!useWrapper) {
        return (
          <label htmlFor={forId} className="pkt-sr-only" aria-describedby={describedBy} id={`${forId}-label`}>
            {label}
          </label>
        )
      }

      if (hasFieldset) {
        return (
          <legend className="pkt-inputwrapper__legend" id={`${forId}-label`}>
            {labelContent}
          </legend>
        )
      }

      return (
        <label className="pkt-inputwrapper__label" htmlFor={forId} aria-describedby={describedBy} id={`${forId}-label`}>
          {labelContent}
        </label>
      )
    }

    const renderHelptext = () => {
      const visibleHelptext = useWrapper ? helptext : undefined
      if (!visibleHelptext && !helptextDropdown) return null

      return (
        <PktHelptext
          forId={forId}
          helptext={visibleHelptext}
          helptextDropdown={helptextDropdown}
          helptextDropdownButton={helptextDropdownButton}
        />
      )
    }

    const errorAlertSize = size === 'medium' ? 'small' : 'xsmall'

    const content = (
      <>
        {renderLabel()}
        {renderHelptext()}
        {counterTop && <Counter />}
        {children}
        {counterBottom && <Counter />}
        {hasError && errorMessage && (
          <div className="pkt-inputwrapper__alert-wrapper">
            <PktAlert skin="error" size={errorAlertSize} aria-live="assertive" role="alert" id={`${forId}-error`}>
              {errorMessage}
            </PktAlert>
          </div>
        )}
      </>
    )

    return (
      <div className={wrapperClasses} role={role} {...focusModality}>
        {hasFieldset ? (
          <fieldset className="pkt-inputwrapper__fieldset" aria-describedby={describedBy}>
            {content}
          </fieldset>
        ) : (
          <div className="pkt-inputwrapper__fieldset">{content}</div>
        )}
      </div>
    )
  },
)

PktInputWrapper.displayName = 'PktInputWrapper'
