import {
  ChangeEvent,
  ReactNode,
  RefObject,
  SessionDataTestId,
  useEffect,
  useRef,
  useState,
} from 'react';
import { motion } from 'framer-motion';
import { isEmpty, isEqual } from 'lodash';
import styled, { CSSProperties } from 'styled-components';
import { THEME_GLOBALS } from '../../themes/globals';
import { AnimatedFlex, Flex } from '../basic/Flex';
import { SpacerMD } from '../basic/Text';
import { SessionIconButton } from '../icon';
import { useHTMLDirection } from '../../util/i18n/rtlSupport';
type TextSizes = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
const StyledSessionInput = styled(Flex)<{
  error: boolean;
  textSize: TextSizes;
}>`
  position: relative;
  width: 100%;
  label {
    color: var(--text-primary-color);
    opacity: 0;
    transition: opacity var(--default-duration);
    text-align: center;
    &.filled {
      opacity: 1;
    }
    &.error {
      color: var(--danger-color);
      font-weight: 700;
      user-select: text;
    }
  }
  input::placeholder,
  textarea::placeholder {
    transition: opacity var(--default-duration) color var(--default-duration);
    ${props => props.error && `color: var(--danger-color); opacity: 1;`}
  }
  ${props =>
    props.textSize &&
    `
  ${StyledInput} {
    font-size: var(--font-size-${props.textSize});
  }
  ${StyledTextAreaContainer} {
    font-size: var(--font-size-${props.textSize});
    textarea {
      &:placeholder-shown {
        font-size: var(--font-size-${props.textSize});
      }
    }
  }
  `}
`;
const StyledBorder = styled(AnimatedFlex)`
  position: relative;
  border: 1px solid var(--input-border-color);
  border-radius: 13px;
`;
const StyledInput = styled(motion.input)<{
  error: boolean;
  textSize: TextSizes;
  centerText?: boolean;
  monospaced?: boolean;
}>`
  outline: 0;
  border: none;
  width: 100%;
  padding: var(--margins-lg);
  background: transparent;
  color: ${props => (props.error ? 'var(--danger-color)' : 'var(--input-text-color)')};
  font-family: ${props => (props.monospaced ? 'var(--font-mono)' : 'var(--font-default)')};
  line-height: 1.4;
  ${props => props.centerText && 'text-align: center;'}
  ${props => `font-size: var(--font-size-${props.textSize});`}
  &::placeholder {
    color: var(--input-text-placeholder-color);
    ${props => props.centerText && 'text-align: center;'}
  }
`;
export const StyledTextAreaContainer = styled(motion.div)<{
  error: boolean;
  textSize: TextSizes;
  centerText?: boolean;
  monospaced?: boolean;
}>`
  display: flex;
  align-items: center;
  position: relative;
  line-height: 1;
  min-height: 80px;
  height: 100%;
  width: 100%;
  padding: 0 var(--margins-md);
  background: transparent;
  color: ${props => (props.error ? 'var(--danger-color)' : 'var(--input-text-color)')};
  outline: 0;
  font-family: ${props => (props.monospaced ? 'var(--font-mono)' : 'var(--font-default)')};
  ${props => `font-size: var(--font-size-${props.textSize});`}
  textarea {
    display: flex;
    height: 100%;
    width: 100%;
    padding: var(--margins-md) 0;
    outline: 0;
    border: none;
    background: transparent;
    resize: none;
    word-break: break-all;
    user-select: all;
    &:placeholder-shown {
      line-height: 1;
      font-family: ${props => (props.monospaced ? 'var(--font-mono)' : 'var(--font-default)')};
      ${props => `font-size: var(--font-size-${props.textSize});`}
    }
    &::placeholder {
      color: var(--input-text-placeholder-color);
    }
  }
`;
const StyledPlaceholder = styled(motion.div)<{
  error: boolean;
  textSize: TextSizes;
  editable: boolean;
  centerText?: boolean;
  monospaced?: boolean;
}>`
  position: relative;
  width: 100%;
  min-height: 80px;
  height: 100%;
  transition: opacity var(--default-duration) color var(--default-duration);
  ${props => props.editable && 'cursor: pointer;'}
  line-height: 1;
  padding: ${props => !props.centerText && 'var(--margins-md) 0'};
  background: transparent;
  color: ${props =>
    props.error
      ? 'var(--danger-color)'
      : props.editable
        ? 'var(--input-text-placeholder-color)'
        : 'var(--input-text-color)'};
  font-family: ${props => (props.monospaced ? 'var(--font-mono)' : 'var(--font-default)')};
  font-size: ${props => `var(--font-size-${props.textSize})`};
  ${props =>
    props.centerText &&
    'text-align: center; display: flex; align-items: center; justify-content: center;'}
`;
const ErrorItem = (props: { id: string; error: string }) => {
  return (
    
      {props.error}
    
  );
};
type ShowHideButtonStrings = { hide: T; show: T };
type ShowHideButtonProps = {
  forceShow: boolean;
  toggleForceShow: () => void;
  error: boolean;
  ariaLabels?: ShowHideButtonStrings;
  dataTestIds?: ShowHideButtonStrings;
};
const ShowHideButton = (props: ShowHideButtonProps) => {
  const {
    forceShow,
    toggleForceShow,
    error,
    ariaLabels = { hide: 'Hide input text button', show: 'Show input text button' },
    dataTestIds = { hide: 'hide-input-text-toggle', show: 'show-input-text-toggle' },
  } = props;
  const htmlDirection = useHTMLDirection();
  const style: CSSProperties = {
    position: 'absolute',
    top: '50%',
    transform: 'translateY(-50%)',
    left: htmlDirection === 'ltr' ? undefined : 'var(--margins-sm)',
    right: htmlDirection === 'ltr' ? 'var(--margins-sm)' : undefined,
  };
  if (forceShow) {
    return (
      
    );
  }
  return (
    
  );
};
const StyledCtaContainer = styled(motion.div)`
  width: 100%;
`;
type Props = {
  error?: string;
  type?: string;
  value?: string;
  placeholder?: string;
  ariaLabel?: string;
  maxLength?: number;
  onValueChanged?: (value: string) => any;
  onEnterPressed?: (value: string) => any;
  autoFocus?: boolean;
  disableOnBlurEvent?: boolean;
  inputRef?: RefObject;
  inputDataTestId?: SessionDataTestId;
  id?: string;
  enableShowHideButton?: boolean;
  showHideButtonAriaLabels?: ShowHideButtonStrings;
  showHideButtonDataTestIds?: ShowHideButtonStrings;
  ctaButton?: ReactNode;
  monospaced?: boolean;
  textSize?: TextSizes;
  centerText?: boolean;
  editable?: boolean;
  isTextArea?: boolean;
  required?: boolean;
  tabIndex?: number;
  className?: string;
};
export const SessionInput = (props: Props) => {
  const {
    placeholder,
    type = 'text',
    value,
    ariaLabel,
    maxLength,
    error,
    onValueChanged,
    onEnterPressed,
    autoFocus,
    disableOnBlurEvent,
    inputRef,
    inputDataTestId,
    id = 'session-input-floating-label',
    enableShowHideButton,
    showHideButtonAriaLabels,
    showHideButtonDataTestIds,
    ctaButton,
    monospaced,
    textSize = 'sm',
    centerText,
    editable = true,
    isTextArea,
    required,
    tabIndex,
    className,
  } = props;
  const [inputValue, setInputValue] = useState('');
  const [errorString, setErrorString] = useState('');
  const [textErrorStyle, setTextErrorStyle] = useState(false);
  const [forceShow, setForceShow] = useState(false);
  const [isFocused, setIsFocused] = useState(props.autoFocus || false);
  const textAreaRef = useRef(inputRef?.current || null);
  const correctType = forceShow ? 'text' : type;
  const updateInputValue = (e: ChangeEvent) => {
    if (!editable) {
      return;
    }
    e.preventDefault();
    const val = e.target.value;
    setInputValue(val);
    setTextErrorStyle(false);
    if (isTextArea && textAreaRef && textAreaRef.current !== null) {
      const scrollHeight = `${textAreaRef.current.scrollHeight}px`;
      if (!autoFocus && isEmpty(val)) {
        // resets the height of the text area so it's centered if we clear the text
        textAreaRef.current.style.height = 'unset';
      }
      if (scrollHeight !== textAreaRef.current.style.height) {
        textAreaRef.current.style.height = `${textAreaRef.current.scrollHeight}px`;
      }
    }
    if (onValueChanged) {
      onValueChanged(val);
    }
  };
  const inputProps: any = {
    id,
    type: correctType,
    placeholder,
    value,
    textSize,
    disabled: !editable,
    maxLength,
    autoFocus,
    'data-testid': inputDataTestId,
    required,
    'aria-required': required,
    tabIndex,
    onChange: updateInputValue,
    style: { paddingInlineEnd: enableShowHideButton ? '48px' : undefined },
    // just in case onChange isn't triggered
    onBlur: (event: ChangeEvent) => {
      if (editable && !disableOnBlurEvent) {
        updateInputValue(event);
        if (isEmpty(value) && !autoFocus && isFocused) {
          setIsFocused(false);
        }
      }
    },
    onKeyDown: (event: KeyboardEvent) => {
      if (!editable) {
        return;
      }
      if (event.key === 'Enter' && onEnterPressed) {
        if (isTextArea && event.shiftKey) {
          return;
        }
        event.preventDefault();
        onEnterPressed(inputValue);
        setErrorString('');
      }
    },
  };
  const containerProps = {
    noValue: isEmpty(value),
    error: textErrorStyle,
    centerText,
    textSize,
    monospaced,
  };
  // if we have an error, we want to show it even if the input changes to a valid value
  useEffect(() => {
    if (error && !isEmpty(error) && !isEqual(error, errorString)) {
      setErrorString(error);
      setTextErrorStyle(!!error);
    }
  }, [error, errorString]);
  useEffect(() => {
    if (isTextArea && editable && isFocused && textAreaRef && textAreaRef.current !== null) {
      textAreaRef.current.focus();
    }
  }, [editable, isFocused, isTextArea]);
  return (
    
      
        {isTextArea ? (
          
            {isFocused ? (
              
            ) : (
               {
                  if (editable) {
                    setIsFocused(true);
                  }
                }}
              >
                {editable ? placeholder : value}
              
            )}
          
        ) : (
          
        )}
        {editable && enableShowHideButton && (
           {
              setForceShow(!forceShow);
            }}
            error={Boolean(errorString)}
            ariaLabels={showHideButtonAriaLabels}
            dataTestIds={showHideButtonDataTestIds}
          />
        )}
      
      {ctaButton || errorString ?  : null}
      {errorString ?  : null}
      
        {ctaButton}
      
    
  );
};