'use client';

import clsx from 'clsx';
import React, { useCallback, useEffect, useRef } from 'react';
import { twMerge } from 'tailwind-merge';

import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import Avatar from '@/components/image/Avatar';
import TextareaV2, { CharCountMode } from '@/components/textarea/TextareaV2';
import { CloseIcon, SendIcon } from '@/icons';

export type CommentInputProps = Pick<
  React.HTMLAttributes<HTMLTextAreaElement>,
  'onKeyDown' | 'onFocus' | 'onFocusCapture' | 'onBlur' | 'onBlurCapture'
> & {
  placeholder: string;
  defaultValue?: string;
  value: string;
  onChange: (
    e: React.ChangeEvent | React.KeyboardEvent | React.MouseEvent,
    value: string
  ) => void;
  onKeyDown?: React.KeyboardEventHandler<HTMLTextAreaElement>;
  onClearClick?: React.MouseEventHandler;
  onSend: (value: string) => void;
  maxLength?: number;
  avatarSrc?: string;
  avatarSize?: number;
  allowLineBreaks?: boolean;
  allowWrapping?: boolean; // wrap onto multiple lines
  rows?: number;
  alwaysShowSend?: boolean;
  sendOnEnterKey?: boolean;
  disabled?: boolean;
  sendDisabled?: boolean;
  ref?: React.RefObject<HTMLTextAreaElement | null>;
};

export type Props = Omit<
  React.HTMLAttributes<HTMLDivElement>,
  | 'onChange'
  | 'onKeyDown'
  | 'onFocus'
  | 'onFocusCapture'
  | 'onBlur'
  | 'onBlurCapture'
  | 'defaultValue'
> &
  CommentInputProps;

const CommentInput: React.FC<Props> = (props) => {
  const {
    defaultValue,
    className,
    avatarSrc,
    placeholder,
    avatarSize = 50,
    value,
    onFocus,
    onFocusCapture,
    onBlur,
    onBlurCapture,
    onChange,
    onKeyDown,
    onClearClick,
    onSend,
    allowLineBreaks = true,
    allowWrapping = true,
    sendOnEnterKey = true,
    alwaysShowSend = false,
    disabled,
    sendDisabled,
    rows = 1,
    maxLength,
    autoFocus,
    ref,
    ...restProps
  } = props;

  // create ref to pass to TextareaV2 if none is passed in
  const internalRef = useRef<HTMLTextAreaElement>(null);
  const textareaRef = ref || internalRef;

  useEffect(() => {
    if (autoFocus && textareaRef && 'current' in textareaRef) {
      textareaRef.current?.focus?.();
    }
  }, [autoFocus, textareaRef]);

  const handleClearClick = useCallback<React.MouseEventHandler>(
    (e) => {
      onChange(e, '');
      if (textareaRef && 'current' in textareaRef) {
        textareaRef.current?.focus();
      }
    },
    [onChange, textareaRef]
  );

  const handleSendClick = useCallback<React.MouseEventHandler>(() => {
    onSend(value);
    if (textareaRef && 'current' in textareaRef) {
      textareaRef.current?.focus();
    }
  }, [value, textareaRef, onSend]);

  const handleTextareaChange = useCallback<
    React.ChangeEventHandler<HTMLTextAreaElement>
  >(
    (e, value = e.currentTarget.value) => {
      onChange(e, value);
    },
    [onChange]
  );

  const handleTextareaKeyDown = useCallback(
    (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
      // allow passed-in onKeyDown handling which can call e.preventDefault() to kill the rest of this logic
      onKeyDown?.(e);
      if (!e.isDefaultPrevented()) {
        if (e.key === 'Enter') {
          if (sendOnEnterKey && !e.shiftKey) {
            // send when enter is pressed w/o shift - enables line break with shift+enter
            e.preventDefault();
            onSend(value);
          } else if (!allowLineBreaks) {
            // prevent keyboard line break
            e.preventDefault();
          }
        }
      }
    },
    [value, sendOnEnterKey, allowLineBreaks, onSend, onKeyDown]
  );

  const showClearButton = !!(value || onClearClick);
  const showSendButton = alwaysShowSend || !!(value && onSend);

  return (
    <div
      className={twMerge(
        'relative flex flex-row items-center gap-2 overflow-hidden rounded-full px-3',
        'bg-(--comment-input-bg,var(--color-background-secondary))',
        className
      )}
      {...restProps}
    >
      <div className='flex shrink-0 items-center justify-center py-3'>
        <Avatar
          className='h-8 w-8'
          src={avatarSrc || null}
          alt='User avatar'
          size={avatarSize}
        />
      </div>
      <TextareaV2
        value={value}
        disabled={disabled}
        placeholder={placeholder}
        className='padding-0 rounded-none border-0 bg-transparent'
        textAreaClassName={clsx(
          'px-0 py-1 text-sm overflow-y-auto max-h-[75px]',
          {
            // if allowLineBreaks is true, force allowWrapping
            'whitespace-nowrap overflow-x-auto': !(
              allowLineBreaks || allowWrapping
            ),
          }
        )}
        onChange={handleTextareaChange}
        onKeyDown={handleTextareaKeyDown}
        rows={rows}
        maxLength={maxLength}
        ref={textareaRef}
        // for character counter inside the text box (diff from designs):
        charCountMode={CharCountMode.Never}
        onFocus={onFocus}
        onFocusCapture={onFocusCapture}
        onBlur={onBlur}
        onBlurCapture={onBlurCapture}
      />
      {(showClearButton || showSendButton) && (
        <div className='flex shrink-0 items-center justify-center gap-2'>
          {showClearButton && (
            <Button
              icon={CloseIcon}
              onClick={onClearClick || handleClearClick}
              size={ButtonSize.Small}
              shape={ButtonShape.Pill}
              variant={ButtonVariant.Standard}
              iconClassName='w-3 h-3'
              className='bg-white/[0.07]'
            />
          )}
          {showSendButton && (
            <Button
              icon={SendIcon}
              onClick={handleSendClick}
              size={ButtonSize.Small}
              shape={ButtonShape.Pill}
              variant={ButtonVariant.Primary}
              iconClassName='w-3 h-3'
              disabled={!value || disabled || sendDisabled}
            />
          )}
        </div>
      )}
    </div>
  );
};

export default CommentInput;
