import React, { useRef, useEffect, CSSProperties, KeyboardEvent, useState, useImperativeHandle } from 'react';
import { useTheme } from '@mui/material/styles';
import './BackstoryTextField.css';

// Define ref interface for exposed methods
interface BackstoryTextFieldRef {
  getValue: () => string;
  setValue: (value: string) => void;
  getAndResetValue: () => string;
}

interface BackstoryTextFieldProps {
  value?: string;
  disabled?: boolean;
  placeholder: string;
  onEnter: (value: string) => void;
  style?: CSSProperties;
}

const BackstoryTextField = React.forwardRef<BackstoryTextFieldRef, BackstoryTextFieldProps>((props, ref) => {
  const {
    value = '',
    disabled = false,
    placeholder,
    onEnter,
    style,
  } = props;
  const theme = useTheme();
  const textareaRef = useRef<HTMLTextAreaElement>(null);
  const shadowRef = useRef<HTMLTextAreaElement>(null);
  const [editValue, setEditValue] = useState<string>(value);

  // Sync editValue with prop value if it changes externally
  useEffect(() => {
    setEditValue(value || "");
  }, [value]);

  // Adjust textarea height based on content
  useEffect(() => {
    if (!textareaRef.current || !shadowRef.current) {
      return;
    }
    const textarea = textareaRef.current;
    const shadow = shadowRef.current;

    // Set shadow value to editValue or placeholder if editValue is empty
    shadow.value = editValue || placeholder;

    // Ensure shadow textarea has same content-relevant styles
    const computed = getComputedStyle(textarea);
    shadow.style.width = computed.width; // Match width for accurate wrapping
    shadow.style.fontSize = computed.fontSize;
    shadow.style.lineHeight = computed.lineHeight;
    shadow.style.fontFamily = computed.fontFamily;
    shadow.style.letterSpacing = computed.letterSpacing;
    shadow.style.wordSpacing = computed.wordSpacing;

    // Use requestAnimationFrame to ensure DOM is settled
    const raf = requestAnimationFrame(() => {
      const paddingTop = parseFloat(computed.paddingTop || '0');
      const paddingBottom = parseFloat(computed.paddingBottom || '0');
      const totalPadding = paddingTop + paddingBottom;

      // Reset height to auto to allow shrinking
      textarea.style.height = 'auto';
      const newHeight = shadow.scrollHeight + totalPadding;

      textarea.style.height = `${newHeight}px`;
    });

    // Cleanup RAF to prevent memory leaks
    return () => cancelAnimationFrame(raf);
  }, [editValue, placeholder]);

  // Expose getValue method via ref
  useImperativeHandle(ref, () => ({
    getValue: () => editValue,
    setValue: (value: string) => setEditValue(value),
    getAndResetValue: () => { const _ev = editValue; setEditValue(''); return _ev; }
  }));

  const handleKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {
    if (event.key === 'Enter' && !event.shiftKey) {
      event.preventDefault(); // Prevent newline
      onEnter(editValue);
      setEditValue(''); // Clear textarea
    }
  };

  const fullStyle: CSSProperties = {
    display: 'flex',
    flexGrow: 1,
    width: '100%',
    padding: '16.5px 14px',
    resize: 'none',
    overflow: 'hidden',
    boxSizing: 'border-box',
    minHeight: 'calc(1.5rem + 28px)', // lineHeight + padding
    lineHeight: '1.5',
    borderRadius: '4px',
    fontSize: '16px',
    backgroundColor: 'rgba(0, 0, 0, 0)',
    fontFamily: theme.typography.fontFamily,
    ...style,
  };

  return (
    <>
      <textarea
        className="BackstoryTextField"
        ref={textareaRef}
        value={editValue}
        disabled={disabled}
        placeholder={placeholder}
        onChange={(e) => setEditValue(e.target.value)}
        onKeyDown={handleKeyDown}
        style={fullStyle}
      />
      <textarea
        className="BackgroundTextField"
        ref={shadowRef}
        aria-hidden="true"
        style={{
          ...fullStyle,
          position: 'absolute',
          top: '-9999px',
          left: '-9999px',
          visibility: 'hidden',
          padding: '0px', // No padding to match content height
          margin: '0px',
          border: '0px', // Remove border to avoid extra height
          height: 'auto', // Allow natural height
          minHeight: '0px',
        }}
        readOnly
        tabIndex={-1}
      />
    </>
  );
});

export type {
  BackstoryTextFieldRef
};

export { BackstoryTextField };