'use client'

import classNames from 'classnames'
import {
  ForwardedRef,
  forwardRef,
  HTMLAttributes,
  ReactNode,
  RefObject,
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react'

import type { TTagSkin } from 'shared-types'

import { PktIcon } from '../icon/Icon'

interface BasePktTagProps {
  skin?: TTagSkin
  textStyle?: 'normal-text' | 'thin-text'
  size?: 'small' | 'medium' | 'large'
  closeTag?: boolean
  iconName?: string
  ariaLabel?: string
  onClose?: () => void
  children?: ReactNode
}

interface ButtonPktTagProps extends BasePktTagProps, HTMLAttributes<HTMLButtonElement> {
  closeTag: true
  type?: 'button' | 'submit' | 'reset'
}

interface SpanPktTagProps extends BasePktTagProps, HTMLAttributes<HTMLSpanElement> {
  closeTag?: false | undefined
  onClose?: undefined
  type?: undefined
}

export type IPktTag = ButtonPktTagProps | SpanPktTagProps

export const PktTag = forwardRef<HTMLSpanElement | HTMLButtonElement, ButtonPktTagProps | SpanPktTagProps>(
  (
    {
      children,
      skin,
      textStyle,
      size,
      closeTag,
      className,
      iconName,
      ariaLabel,
      onClose,
      type,
      'aria-description': ariaDescriptionPropValue,
      ...props
    }: ButtonPktTagProps | SpanPktTagProps,
    forwardedRef: ForwardedRef<HTMLElement>,
  ) => {
    const [isClosed, setClosed] = useState<boolean>(false)

    const close = useCallback(() => {
      setClosed(true)
      if (onClose) {
        onClose()
      }
    }, [onClose])

    const spanRef: RefObject<HTMLButtonElement | HTMLSpanElement | null> = useRef<HTMLButtonElement | HTMLSpanElement>(null)
    const [labelText, setLabelText] = useState('')

    useEffect(() => {
      setLabelText(spanRef.current?.textContent?.trim() ?? '')
    }, [children])

    const ariaDescription = useMemo(() => {
      if (closeTag && !ariaLabel) return (labelText && `Klikk for å fjerne ${labelText}`) || ariaDescriptionPropValue
    }, [closeTag, ariaLabel, labelText, ariaDescriptionPropValue])

    const classes = {
      'pkt-tag': true,
      [`pkt-tag--${size}`]: !!size,
      [`pkt-tag--${skin}`]: !!skin,
      [`pkt-tag--${textStyle}`]: !!textStyle,
    }

    const btnClasses = {
      'pkt-tag': true,
      'pkt-btn': true,
      'pkt-btn--tertiary': true,
      [`pkt-tag--${textStyle}`]: !!textStyle,
      [`pkt-tag--${size}`]: !!size,
      [`pkt-tag--${skin}`]: !!skin,
      'pkt-btn--icons-right-and-left': closeTag && !!iconName,
      'pkt-hide': isClosed,
    }

    if (closeTag) {
      return (
        <button
          {...props}
          className={classNames(btnClasses, className)}
          type={type}
          onClick={close}
          aria-label={ariaLabel}
          aria-description={ariaDescription}
          ref={forwardedRef as ForwardedRef<HTMLButtonElement>}
        >
          {iconName && <PktIcon className={'pkt-tag__icon'} name={iconName} />}
          <span ref={spanRef}>{children}</span>
          <PktIcon className={'pkt-tag__close-btn'} name={'close'} />
        </button>
      )
    } else {
      return (
        <span {...props} className={classNames(classes, className)} ref={forwardedRef as ForwardedRef<HTMLSpanElement>}>
          {iconName && <PktIcon className={'pkt-tag__icon'} name={iconName} aria-hidden="true" />}
          <span ref={spanRef}>{children}</span>
        </span>
      )
    }
  },
)

PktTag.displayName = 'PktTag'
