import { Button, Flex } from 'antd';
import type { InputRef } from 'antd';
import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
import './ButtonEditableInputUI.css';
import { InputUI } from '../../primitives/input';
import { createValidInputPlugin } from '../../primitives/input/plugins';
import type { InputCommitPlugin, InputUIProps, InputValidator } from '../../primitives/input';

export type ButtonEditableInputUIProps = Omit<
  InputUIProps,
  'commitPlugins' | 'readOnly'
> & {
  onValid?: InputValidator;
  commitPlugins?: ReadonlyArray<InputCommitPlugin>;
  editButtonLabel?: string;
  confirmButtonLabel?: string;
};

export const ButtonEditableInputUI = forwardRef<InputRef, ButtonEditableInputUIProps>(
  function ButtonEditableInputUI(
    {
      onValid,
      commitPlugins = [],
      editButtonLabel = '수정',
      confirmButtonLabel = '확인',
      disabled,
      onBlur,
      onPressEnter,
      ...restProps
    },
    ref,
  ) {
    const inputRef = useRef<InputRef>(null);
    const [isEditing, setIsEditing] = useState(false);

    useImperativeHandle(ref, () => inputRef.current as InputRef, []);

    useEffect(() => {
      if (!isEditing) {
        return;
      }

      inputRef.current?.focus({
        cursor: 'all',
      });
    }, [isEditing]);

    const mergedCommitPlugins = onValid
      ? [createValidInputPlugin(onValid), ...commitPlugins]
      : [...commitPlugins];
    const inputClassName = [restProps.className, !isEditing ? 'button-editable-input__field--readonly' : '']
      .filter(Boolean)
      .join(' ');

    return (
      <Flex gap="small" align="center" className="button-editable-input">
        <InputUI
          {...restProps}
          ref={inputRef}
          className={inputClassName}
          disabled={disabled}
          readOnly={!isEditing}
          commitPlugins={mergedCommitPlugins}
          onBlur={(event) => {
            setIsEditing(false);
            onBlur?.(event);
          }}
          onPressEnter={(event) => {
            setIsEditing(false);
            onPressEnter?.(event);
          }}
        />
        <Button
          disabled={disabled}
          className={!isEditing ? 'button-editable-input__button--readonly' : undefined}
          onMouseDown={(event) => {
            if (isEditing) {
              event.preventDefault();
            }
          }}
          onClick={() => {
            if (!isEditing) {
              setIsEditing(true);
              return;
            }

            setIsEditing(false);
            inputRef.current?.blur();
          }}
        >
          {isEditing ? confirmButtonLabel : editButtonLabel}
        </Button>
      </Flex>
    );
  },
);
