import React, {
  RefObject,
  TextareaHTMLAttributes,
  useEffect,
  useRef,
} from 'react';
import { twMerge } from 'tailwind-merge';

export interface TextareaProps
  extends TextareaHTMLAttributes<HTMLTextAreaElement> {
  maxLength: number;
  placeholder: string;
  value: string;
  onChange: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;
  onClick?: (event: React.MouseEvent<HTMLTextAreaElement, MouseEvent>) => void;
  onKeyDown?: (event: React.KeyboardEvent<HTMLTextAreaElement>) => void;
  isReadOnly?: boolean;
  cursor?: string;
  leftAsset?: React.ReactNode;
  customHeight?: string;
  spacedLeftAsset?: boolean;
  resize?: boolean;
  onClear?: () => void;
  isScrollable?: boolean;
  enableExtraMargin?: boolean;
  bgColor?: string;
  paddingBottom?: number;
  className?: string;
  textareaClassName?: string;
  ref?: RefObject<any>;
  showMaxLengthAtCharsRemaining?: number;
  maxLengthClassName?: string;
  withInsetShadow?: boolean;
  explicitHeight?: number;
}

const Textarea: React.FC<TextareaProps> = ({
  ref,
  className,
  textareaClassName,
  maxLength,
  placeholder,
  value,
  onChange,
  onClick,
  onKeyDown,
  isReadOnly,
  cursor,
  leftAsset,
  customHeight = 'h-[36px]',
  spacedLeftAsset = false,
  resize = false,
  onClear,
  isScrollable,
  enableExtraMargin = false,
  bgColor = 'background-tertiary',
  paddingBottom = 40,
  showMaxLengthAtCharsRemaining,
  maxLengthClassName,
  withInsetShadow = false,
  explicitHeight,
  ...restProps
}) => {
  const _ref = useRef<any>(null);
  const cursorPositionRef = useRef<any>(null);
  const textareaRef = ref || _ref;
  useEffect(() => {
    if (textareaRef.current && cursorPositionRef.current !== null) {
      textareaRef.current.setSelectionRange(
        cursorPositionRef.current,
        cursorPositionRef.current
      );
    }
  }, [value]);
  return (
    <div
      className={twMerge(
        `relative flex flex-1 flex-col overflow-hidden rounded-lg border border-border-primary text-foreground-primary bg-${bgColor}`,
        className
      )}
      style={{
        paddingBottom: `${paddingBottom}px`,
        marginBottom: enableExtraMargin ? '12px' : '0',
        boxShadow: withInsetShadow
          ? 'inset 0px 0px 6px 0px rgba(0,0,0,0.1)'
          : undefined,
        height:
          explicitHeight !== undefined ? `${explicitHeight}px` : undefined,
      }}
    >
      <textarea
        ref={textareaRef}
        maxLength={maxLength}
        value={value}
        onChange={(e) => {
          const newCursorPosition = e.target.selectionStart;
          cursorPositionRef.current = newCursorPosition;
          onChange?.(e);
        }}
        placeholder={placeholder}
        onClick={onClick}
        onKeyDown={onKeyDown}
        readOnly={isReadOnly}
        className={twMerge(
          `custom-textarea text-14px w-full flex-1 p-4 pb-8 font-sans text-foreground-primary focus:outline-none ${customHeight} ${cursor ? cursor : 'text'} placeholder:lighterGray placeholder:select-none ${resize ? 'resize-y' : 'resize-none'} ${customHeight} bg-${bgColor}`,
          textareaClassName
        )}
        style={{
          overflowY: isScrollable ? 'auto' : 'hidden',
          overflowX: 'hidden',
        }}
        {...restProps}
      />
      {!showMaxLengthAtCharsRemaining ||
      maxLength - value.length < showMaxLengthAtCharsRemaining ? (
        <div
          className={twMerge(
            `absolute font-sans ${spacedLeftAsset ? 'bottom-[52px]' : 'bottom-2'} right-2 rounded-full bg-background-tertiary p-2 text-sm text-foreground-secondary`,
            maxLengthClassName
          )}
        >
          {value.length} / {maxLength}
        </div>
      ) : null}
      {leftAsset && (
        <div
          className={`absolute bottom-2 left-2 max-w-full overflow-x-auto whitespace-nowrap`}
        >
          {leftAsset}
        </div>
      )}
      {onClear && (
        <button
          type='button'
          onClick={onClear}
          className='absolute top-4 right-4 text-foreground-secondary'
          style={{ background: 'none', border: 'none', cursor: 'pointer' }}
        >
          &#x2715;
        </button>
      )}
    </div>
  );
};

export default Textarea;
