'use client'

import type { ComponentProps, ReactNode } from 'react'

import type { GDSComponentProps } from '@graphprotocol/gds-css'

import { useCSSPropsPolyfill, useGDS } from '../hooks/index.ts'
import { cn, getCSSPropsAttributes, splitProps, trimReactNode } from '../utils/index.ts'
import { renderAddon, type AddonValue } from './base/Addon.tsx'
import { LabelMeta } from './Label.meta.ts'

export interface LabelProps extends ComponentProps<'span'>, GDSComponentProps<typeof LabelMeta> {
  htmlFor?: string | undefined
  description?:
    | ReactNode
    | ({ content: ReactNode } & Omit<ComponentProps<'span'>, 'children' | 'content'>)
    | undefined
  addon?: AddonValue | undefined
}

export function Label({
  variant,
  size,
  description,
  addon,
  className,
  style,
  children,
  ...props
}: LabelProps) {
  useGDS()

  const { rootProps, nestedProps } = splitProps(props)

  const [cssPropsPolyfillRef, cssPropsPolyfillAttributes] = useCSSPropsPolyfill(LabelMeta, {
    variant,
    size,
  })
  const NestedElement = (props.htmlFor ? 'label' : 'span') as 'span'

  const {
    content: descriptionContent,
    className: descriptionClassName,
    ...descriptionProps
  } = typeof description === 'object' && description !== null && 'content' in description
    ? description
    : { content: description }

  return (
    <span
      ref={cssPropsPolyfillRef}
      className={cn('gds-label root-flex flex-col gap-1 u:wrap-anywhere', className)}
      {...getCSSPropsAttributes(LabelMeta, { variant, size }, style)}
      {...cssPropsPolyfillAttributes}
      {...rootProps}
    >
      {children ? (
        <span
          className={`
            truncate whitespace-nowrap
            @prop-variant-primary/label:text-default
            @prop-variant-secondary/label:text-muted
            @prop-size-small/label:text-12
            @prop-size-medium/label:text-14
            @prop-size-large/label:text-16
          `}
        >
          <NestedElement className="nested/label-ref inline whitespace-normal" {...nestedProps}>
            {trimReactNode(children)}
          </NestedElement>
          {addon ? (
            <>
              {/* Zero-width non-breaking space, to prevent a line break between the text and the addon */}
              &#8288;
              <span
                className={`
                  gds-addon root-flex/inline items-center justify-center align-top
                  u:ms-(--gap-addon) u:h-lh u:min-w-(--gds-addon-size) u:shrink-0
                  u:@prop-size-small/label:addon-small
                  u:@prop-size-medium/label:addon-small
                  u:@prop-size-large/label:addon-medium
                `}
              >
                {renderAddon(addon)}
              </span>
            </>
          ) : null}
        </span>
      ) : null}
      {descriptionContent ? (
        <span
          className={cn(
            `u:@prop-variant-primary/label:text-muted
            u:@prop-variant-secondary/label:text-subtle
            u:@prop-size-small/label:text-12
            u:@prop-size-medium/label:text-12
            u:@prop-size-large/label:text-14`,
            descriptionClassName,
          )}
          {...descriptionProps}
        >
          {descriptionContent}
        </span>
      ) : null}
    </span>
  )
}
