import * as Ariakit from '@ariakit/react';
import { getClassNames } from '@websolutespa/bom-core';
import { ComponentPropsWithRef, forwardRef, ReactNode, useState } from 'react';
import styled from 'styled-components';
import { UIComponentWithRef, UIStyledComponentProps } from '../../components/types';
import { getCssResponsive } from '../../components/utils';
import { getVariantKey, useVariants } from '../../variants';
import { IInputVariants, inputVariants } from './input.variants';

const StyledInputContainer = styled.div<InputProps>`
  ${props => getVariantKey('container', props.variant, props.variants)}
  ${props => getCssResponsive(props)}
`;

const StyledInput = styled(Ariakit.FormInput) <Ariakit.FormInputProps & InputProps>`
  ${props => getVariantKey('input', props.variant, props.variants)}
  ${props => getCssResponsive(props)}
`;

type Props = ComponentPropsWithRef<'input'> & {
  before?: ReactNode;
  after?: ReactNode;
  variant?: keyof typeof inputVariants | (string & {});
  variants?: IInputVariants;
};

export type InputProps = UIStyledComponentProps<Props, 'input'>;

export type InputComponent<C extends React.ElementType = 'input'> = UIComponentWithRef<C, Props>;

// id -> uniqueName preferred for label htmlFor
// name -> name attribute of input value

export const Input: InputComponent = forwardRef(
  function Input({
    as = 'input',
    className,
    before,
    after,
    type = 'text',
    onFocus,
    onBlur,
    variant = 'default',
    variants,
    id,
    name,
    ...props
  }, ref) {
    const [focus, setFocus] = useState<boolean>(false);
    const onFocus_ = (event: React.FocusEvent<HTMLInputElement>) => {
      onFocus && onFocus(event);
      setFocus(true);
    };
    const onBlur_ = (event: React.FocusEvent<HTMLInputElement>) => {
      onBlur && onBlur(event);
      setFocus(false);
    };
    const classNames = getClassNames('input__group', {
      focus,
      disabled: props.disabled,
      readonly: props.readOnly,
      hidden: props.hidden,
    }, className, variant);
    const globalVariants = useVariants('input', inputVariants);
    variants = variants || globalVariants;
    return (
      <StyledInputContainer
        className={classNames}
        variant={variant}
        variants={variants}
        data-focus-visible={focus || undefined}
      >
        {before}
        <StyledInput
          className={'input'}
          ref={ref}
          as={as}
          type={type}
          id={id || name}
          name={name}
          variant={variant}
          variants={variants}
          onFocus={onFocus_}
          onBlur={onBlur_}
          {...props}
        />
        {after}
      </StyledInputContainer>
    );
  });
