'use client';

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

export type Props = Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> &
  Pick<
    React.InputHTMLAttributes<HTMLInputElement>,
    'maxLength' | 'onChange' | 'onKeyDown' | 'onBlur' | 'onFocus'
  > & {
    inputClassName?: string;
    value?: string;
    children?: string;
    disabled?: boolean;
    onValueChange?: (value: string) => void;
    onValueCommit?: (value: string) => void;
  };

/**
 * One-line text input that looks like normal display text until you click on it
 */
const TextEditable: React.FC<Props> = (props) => {
  const {
    className,
    children,
    inputClassName,
    value = children,
    disabled,
    onValueChange,
    onValueCommit,
    onChange,
    onKeyDown,
    onBlur,
    onFocus,
    maxLength,
    ...restProps
  } = props;

  const handleChange = useCallback<React.FormEventHandler<HTMLInputElement>>(
    (e) => {
      onChange?.(e);
      if (!e.isDefaultPrevented()) {
        onValueChange?.(e.currentTarget.value);
      }
    },
    [onChange, onValueChange]
  );

  const handleBlur = useCallback<React.FocusEventHandler<HTMLInputElement>>(
    (e) => {
      onBlur?.(e);
      if (!e.isDefaultPrevented()) {
        onValueCommit?.(e.currentTarget.value);
      }
    },
    [onBlur, onValueCommit]
  );

  const handleKeyDown = useCallback<
    React.KeyboardEventHandler<HTMLInputElement>
  >(
    (e) => {
      onKeyDown?.(e);
      if (!e.isDefaultPrevented()) {
        if (e.key === 'Enter' || e.key === 'Escape') {
          e.preventDefault();
          e.currentTarget.blur();
        }
      }
    },
    [onKeyDown]
  );

  return (
    <div
      {...restProps}
      className={twMerge(
        'focus-within:[&>input]:border-foreground-primary',
        className
      )}
    >
      <input
        type='text'
        className={twMerge(
          'font-inherit leading-inherit tracking-inherit block w-full overflow-hidden border-b-2 border-border-primary bg-transparent text-ellipsis whitespace-nowrap text-inherit outline-none hover:cursor-pointer focus:cursor-text disabled:cursor-auto',
          inputClassName
        )}
        value={value}
        disabled={disabled}
        maxLength={maxLength}
        onChange={onChange || onValueChange ? handleChange : undefined}
        onBlur={onBlur || onValueCommit ? handleBlur : undefined}
        onFocus={onFocus}
        onKeyDown={handleKeyDown}
      />
    </div>
  );
};

export default TextEditable;
