'use client'

import type { ComponentProps } from 'react'

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

import { useControlled, useGDS } from '../hooks/index.ts'
import { cn, splitProps } from '../utils/index.ts'
import { Field, type FieldProps } from './base/Field.tsx'
import type { TextAreaMeta } from './TextArea.meta.ts'

export interface TextAreaProps
  extends
    Omit<ComponentProps<'textarea'>, 'onChange' | 'children'>,
    GDSComponentProps<typeof TextAreaMeta> {
  label?: FieldProps['label'] | undefined
  description?: FieldProps['description'] | undefined
  placeholder?: string | undefined
  name?: string | undefined
  value?: string | undefined
  defaultValue?: string | undefined
  onChange?: ((value: string) => void) | undefined
  maxLength?: number | undefined
  /** @default false */
  disabled?: boolean | undefined
  /** @default false */
  readOnly?: boolean | undefined
  status?: FieldProps['status'] | undefined
  message?: FieldProps['message'] | undefined
}

export function TextArea({
  size,
  label,
  'aria-label': ariaLabel,
  'aria-labelledby': ariaLabelledBy,
  description,
  placeholder,
  name,
  value: controlledValue,
  defaultValue,
  onChange,
  maxLength,
  disabled = false,
  readOnly = false,
  status,
  message,
  className,
  ...props
}: TextAreaProps) {
  useGDS()

  const { rootProps, nestedProps } = splitProps(props)

  const [value, setValue] = useControlled(controlledValue, defaultValue ?? '', onChange)

  return (
    <Field
      size={size}
      label={label}
      aria-label={ariaLabel}
      aria-labelledby={ariaLabelledBy}
      description={description}
      placeholder={placeholder}
      name={name}
      value={value}
      maxLength={maxLength}
      disabled={disabled || (readOnly ? 'read-only' : false)}
      status={status}
      message={message}
      className={cn('gds-text-area', className)}
      {...rootProps}
      renderInput={(renderProps, { inputProps }) => (
        <Field.Box {...renderProps}>
          <div className="flex">
            <textarea
              {...inputProps}
              onChange={(event) => {
                setValue(event.target.value)
              }}
              className={cn(
                inputProps.className,
                /**
                 * The `w-0` and `flex-1` classes are to work around `textarea` having a default but
                 * useless intrinsic width. When `field-sizing` is supported everywhere, we should
                 * switch to that.
                 */
                `max-h-64 w-0 min-w-16 flex-1
                @prop-size-small/field:h-24
                @prop-size-small/field:min-h-12
                @prop-size-small/field:p-2
                @prop-size-medium/field:h-28
                @prop-size-medium/field:min-h-14
                @prop-size-medium/field:p-3
                @prop-size-large/field:h-32
                @prop-size-large/field:min-h-16
                @prop-size-large/field:p-3`,
              )}
              {...nestedProps}
            />
          </div>
        </Field.Box>
      )}
    />
  )
}
