import clsx from 'clsx';
import { LegacyRef, forwardRef, useMemo } from 'react';
import TextareaAutosize, {
  type TextareaAutosizeProps,
} from 'react-textarea-autosize';
import { twMerge } from 'tailwind-merge';

import CharacterCount from './CharacterCount';

export enum CharCountMode {
  Always = 'Always',
  WhenCloseToFull = 'WhenCloseToFull',
  Never = 'Never',
}

export type TextareaV2Props = {
  charCountMode?: CharCountMode;
  resize?: boolean;
  value: string;
  textAreaClassName?: string;
  characterCountClassName?: string;
  ref?: LegacyRef<HTMLTextAreaElement>;
} & TextareaAutosizeProps;

const TextareaV2: React.FC<TextareaV2Props> = forwardRef(function TextareaV2(
  {
    maxLength,
    value,
    charCountMode = CharCountMode.WhenCloseToFull,
    resize = false,
    readOnly,
    className,
    textAreaClassName,
    characterCountClassName,
    disabled,

    ...restProps
  },
  ref: React.ForwardedRef<HTMLTextAreaElement>
) {
  const showCharCount = useMemo(() => {
    if (charCountMode === CharCountMode.Never || !maxLength) {
      return false;
    } else if (charCountMode === CharCountMode.Always) {
      return true;
    } else if (charCountMode === CharCountMode.WhenCloseToFull) {
      return value.length >= maxLength * 0.8;
    } else {
      throw new Error(`Invalid charCountMode: ${charCountMode}`);
    }
  }, [charCountMode, maxLength, value.length]);

  return (
    <div
      className={twMerge(
        `relative flex-1 overflow-hidden rounded-lg border border-border-primary bg-transparent p-0.5`,
        className
      )}
    >
      <TextareaAutosize
        ref={ref}
        className={twMerge(
          clsx(
            'custom-textarea block w-full bg-inherit p-3 font-sans text-[16px] placeholder:text-foreground-secondary focus:outline-none',
            {
              'text-foreground-primary': !disabled,
              'text-foreground-secondary': disabled,
              cursor: readOnly ? 'not-allowed' : 'text',
              ['resize-vertical']: resize,
              ['resize-none']: !resize,
              ['overflow-hidden']: !resize,
              ['overflow-auto']: resize,
              'pb-4': !showCharCount,
              'pb-[1.8rem]': showCharCount,
            }
          ),
          textAreaClassName
        )}
        disabled={disabled}
        maxLength={maxLength}
        value={value}
        readOnly={readOnly}
        {...restProps}
      />
      {showCharCount && (
        <div
          className={twMerge(
            'absolute right-2 bottom-2 rounded bg-inherit px-0.5 font-sans text-sm text-foreground-secondary before:absolute before:inset-0 before:rounded-[inherit]',
            characterCountClassName
          )}
        >
          <CharacterCount
            className='relative'
            okayClassName='text-foreground-secondary'
            errorClassName='text-accent-error-on-primary'
            length={value.length}
            maxLength={maxLength ?? Infinity}
          />
        </div>
      )}
    </div>
  );
});

export default TextareaV2;
