'use client'

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

import { PktAlert } from '../alert/Alert'
import { PktButton } from '../button/Button'

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'
}

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',
    }: IPktInputWrapper,
    ref: ForwardedRef<HTMLDivElement>,
  ) => {
    const [isHelpTextOpen, setIsHelpTextOpen] = useState(false)

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

    const toggleHelpText = () => setIsHelpTextOpen((prev) => !prev)

    const wrapperClasses = [
      'pkt-inputwrapper',
      className,
      hasError ? 'pkt-inputwrapper--error' : '',
      disabled ? 'pkt-inputwrapper--disabled' : '',
      inline ? 'pkt-inputwrapper--inline' : '',
    ]
      .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 = () => {
      if (!helptext && !helptextDropdown) return null

      return (
        <>
          {helptext && useWrapper && (
            <div className="pkt-inputwrapper__helptext" id={`${forId}-helptext`}>
              {helptext}
            </div>
          )}
          {helptextDropdown && (
            <div className="pkt-inputwrapper__helptext-expandable">
              <PktButton
                skin="tertiary"
                size="small"
                variant="icon-right"
                iconName={isHelpTextOpen ? 'chevron-thin-up' : 'chevron-thin-down'}
                className="pkt-link pkt-link--icon-right"
                onClick={toggleHelpText}
              >
                <span
                  dangerouslySetInnerHTML={{
                    __html: helptextDropdownButton ?? 'Les mer <span class="pkt-sr-only">om inputfeltet</span>',
                  }}
                />
              </PktButton>
              <div
                className={`pkt-inputwrapper__helptext ${
                  isHelpTextOpen
                    ? 'pkt-inputwrapper__helptext-expandable-open'
                    : 'pkt-inputwrapper__helptext-expandable-closed'
                }`}
              >
                {helptextDropdown}
              </div>
            </div>
          )}
        </>
      )
    }

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

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

PktInputWrapper.displayName = 'PktInputWrapper'
